template<class T, class U>
concept same-as-impl = is_same_v<T, U>; // exposition only
template<class T, class U>
concept same_as = same-as-impl<T, U> && same-as-impl<U, T>;
template<class Derived, class Base>
concept derived_from =
is_base_of_v<Base, Derived> &&
is_convertible_v<const volatile Derived*, const volatile Base*>;
template<class From, class To>
concept convertible_to =
is_convertible_v<From, To> &&
requires {
static_cast<To>(declval<From>());
};
template<class T, class U>
concept common_reference_with =
same_as<common_reference_t<T, U>, common_reference_t<U, T>> &&
convertible_to<T, common_reference_t<T, U>> &&
convertible_to<U, common_reference_t<T, U>>;
template<class T, class U>
concept common_with =
same_as<common_type_t<T, U>, common_type_t<U, T>> &&
requires {
static_cast<common_type_t<T, U>>(declval<T>());
static_cast<common_type_t<T, U>>(declval<U>());
} &&
common_reference_with<
add_lvalue_reference_t<const T>,
add_lvalue_reference_t<const U>> &&
common_reference_with<
add_lvalue_reference_t<common_type_t<T, U>>,
common_reference_t<
add_lvalue_reference_t<const T>,
add_lvalue_reference_t<const U>>>;
template<class T>
concept integral = is_integral_v<T>;
template<class T>
concept signed_integral = integral<T> && is_signed_v<T>;
template<class T>
concept unsigned_integral = integral<T> && !signed_integral<T>;
template<class T>
concept floating_point = is_floating_point_v<T>;
template<class LHS, class RHS>
concept assignable_from =
is_lvalue_reference_v<LHS> &&
common_reference_with<const remove_reference_t<LHS>&, const remove_reference_t<RHS>&> &&
requires(LHS lhs, RHS&& rhs) {
{ lhs = std::forward<RHS>(rhs) } -> same_as<LHS>;
};
template<class T, class U>
concept swappable_with =
common_reference_with<T, U> &&
requires(T&& t, U&& u) {
ranges::swap(std::forward<T>(t), std::forward<T>(t));
ranges::swap(std::forward<U>(u), std::forward<U>(u));
ranges::swap(std::forward<T>(t), std::forward<U>(u));
ranges::swap(std::forward<U>(u), std::forward<T>(t));
};
template<class T>
concept destructible = is_nothrow_destructible_v<T>;
template<class T, class... Args>
concept constructible_from = destructible<T> && is_constructible_v<T, Args...>;
template<class T>
constexpr bool is-default-initializable = see below; // exposition only
template<class T>
concept default_initializable = constructible_from<T> &&
requires { T{}; } &&
is-default-initializable<T>;
template<class T>
concept move_constructible = constructible_from<T, T> && convertible_to<T, T>;
template<class T>
concept copy_constructible =
move_constructible<T> &&
constructible_from<T, T&> && convertible_to<T&, T> &&
constructible_from<T, const T&> && convertible_to<const T&, T> &&
constructible_from<T, const T> && convertible_to<const T, T>;