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