Concepts

Concepts

Identifiers should be written in CamelCase.

template<typename T, typename U>
concept ConvertibleTo = std::convertible_to<std::decay_t<T>,std::decay_t<U>>;

Requirements

Do not indent multiline requires clauses.

template<typename T>
concept Referenceable =
requires
{
  typename Reference<T>;
  typename ConstReference<T>;
};

   For conjunctions, disjunctions and atomic constrains follow the models below:

Do not use traits directly, alias them as concepts

template<typename T>
concept Integral = std::is_integral_v<T>;

template<typename T>
concept Floating = std::is_floating_point_v<T>;

One line disjunctions (can be also applied to conjunctions)

template<typename T>
concept Arithmetic = Integral<T> || Floating<T>;

Multiline disjunctions (can be also applied to conjunctions)

template<typename T>
concept Arithmetic =
Integral<T>
|| Floating<T>
|| requires(T t)
  {
    { t+t } -> std::same_as<T>;
    { t-t } -> std::same_as<T>;
    { t*t } -> std::same_as<T>;
    { t/t } -> std::same_as<T>;
  };

   One level of indentation is allowed in this scenario.

Parameter packs with fold expressions

// Is U pairs of a type T?
template<typename T, typename... U>
concept IsPairsOf =
requires(U... u)
{
  { ((u.first),...) } -> std::convertible_to<std::decay_t<T>>;
  { ((u.second),...) } -> std::convertible_to<std::decay_t<T>>;
};