[temp.constr.atomic] (original) (raw)

13 Templates [temp]

13.5 Template constraints [temp.constr]

13.5.2 Constraints [temp.constr.constr]

13.5.2.3 Atomic constraints [temp.constr.atomic]

An atomic constraint is formed from an expression Eand a mapping from the template parameters that appear within E to template arguments that are formed via substitution during constraint normalization in the declaration of a constrained entity (and, therefore, can involve the unsubstituted template parameters of the constrained entity), called the parameter mapping ([temp.constr.decl]).

[Note 2:

The comparison of parameter mappings of atomic constraints operates in a manner similar to that of declaration matching with alias template substitution ([temp.alias]).

[Example 1: template <unsigned N> constexpr bool Atomic = true;template <unsigned N> concept C = Atomic<N>;template <unsigned N> concept Add1 = C<N + 1>;template <unsigned N> concept AddOne = C<N + 1>;template <unsigned M> void f() requires Add1<2 * M>;template <unsigned M> int f() requires AddOne<2 * M> && true;int x = f<0>(); template <unsigned N> struct WrapN;template <unsigned N> using Add1Ty = WrapN<N + 1>;template <unsigned N> using AddOneTy = WrapN<N + 1>;template <unsigned M> void g(Add1Ty<2 * M> *);template <unsigned M> void g(AddOneTy<2 * M> *);void h() { g<0>(nullptr); } — _end example_]

As specified in [temp.over.link], if the validity or meaning of the program depends on whether two constructs are equivalent, and they are functionally equivalent but not equivalent, the program is ill-formed, no diagnostic required.

[Example 2: template <unsigned N> void f2() requires Add1<2 * N>;template <unsigned N> int f2() requires Add1<N * 2> && true;void h2() { f2<0>(); } — _end example_]

— _end note_]

To determine if an atomic constraint issatisfied, the parameter mapping and template arguments are first substituted into its expression.

If substitution results in an invalid type or expression in the immediate context of the atomic constraint ([temp.deduct.general]), the constraint is not satisfied.

Otherwise, the lvalue-to-rvalue conversionis performed if necessary, and E shall be a constant expression of type bool.

The constraint is satisfied if and only if evaluation of Eresults in true.

If, at different points in the program, the satisfaction result is different for identical atomic constraints and template arguments, the program is ill-formed, no diagnostic required.

[Example 3: template<typename T> concept C = sizeof(T) == 4 && !true; template<typename T> struct S { constexpr operator bool() const { return true; } };template<typename T> requires (S<T>{}) void f(T); void f(int); void g() { f(0); } — _end example_]