libcruft-util/concepts/named.hpp

95 lines
2.6 KiB
C++

#pragma once
#include <iterator>
#include <concepts>
#include <utility>
///////////////////////////////////////////////////////////////////////////////
// C++ named requirements
namespace cruft::concepts::named {
/// Corresponds to the "Container" named requirement.
template <class T>
concept container =
std::default_initializable<T> and
std::copy_constructible<T> and
std::move_constructible<T> and
std::destructible<T> and
std::equality_comparable<T> and
requires (T a, T b)
{
typename T::value_type;
typename T::reference;
typename T::const_reference;
typename T::iterator;
typename T::const_iterator;
typename T::difference_type;
typename T::size_type;
{ a = b } -> std::same_as<T&>;
{ a = std::move (b) } -> std::same_as<T&>;
{ a.begin () } -> std::same_as<typename T::iterator>;
{ a.end () } -> std::same_as<typename T::iterator>;
{ a.cbegin () } -> std::same_as<typename T::const_iterator>;
{ a.cend () } -> std::same_as<typename T::const_iterator>;
{ a.swap (b) } -> std::same_as<void>;
{ std::swap (a, b) } -> std::same_as<void>;
{ a.size () } -> std::same_as<typename T::size_type>;
{ a.max_size () } -> std::same_as<typename T::size_type>;
{ a.empty () } -> std::same_as<bool>;
};
template <typename T>
concept move_assignable =
requires (T a, T b)
{
{ a = std::move (b) } -> std::same_as<T&>;
};
template <typename T>
concept copy_assignable =
move_assignable<T> &&
requires (T a, T b)
{
{ a = b } -> std::same_as<T&>;
};
template <typename T>
concept legacy_iterator =
std::copy_constructible<T> &&
copy_assignable<T> &&
std::destructible<T> &&
std::swappable<T> &&
requires (T t)
{
typename std::iterator_traits<T>::value_type;
typename std::iterator_traits<T>::difference_type;
typename std::iterator_traits<T>::reference;
typename std::iterator_traits<T>::pointer;
typename std::iterator_traits<T>::iterator_category;
{ *t };
{ ++t } -> std::same_as<T&>;
};
template <typename T>
concept legacy_input_iterator =
legacy_iterator<T> &&
std::equality_comparable<T> &&
requires (T a, T b)
{
typename std::iterator_traits<T>::reference;
typename std::iterator_traits<T>::value_type;
{ a != b } -> std::same_as<bool>;
{ ++a } -> std::same_as<T&>;
{ a++ };
};
}