C++2a(C++20)コンセプトにおける原始制約(atomic constraint)では、パラメータ置換(parameter mapping)の失敗はハードエラー(ill-formed)を引き起こさず、その制約式を満たさない(not satisfied)と解釈される。C++17現在はstd::void_t
やstd::conjunction
を駆使した難解なテンプレートメタプログラミング技法が要求されるが、C++2aでは単純な制約式記述によるコンセプト定義により代替される。はず。\\\\٩( 'ω' )و ////
ある型T
がT::value_type = int
型を定義するか確認するメタ関数/コンセプトIntContainer
の実装例。
// C++17 #include <type_traits> // 補助メタ関数 HasValueType template <class, class = std::void_t<>> struct HasValueType : std::false_type {}; template <class T> struct HasValueType<T, std::void_t<typename T::value_type>> : std::true_type {}; // 補助メタ関数 IntValueType template <typename T> struct IntValueType : std::is_same<typename T::value_type, int> {}; template <typename T> using IntContainer = std::conjunction<HasValueType<T>, IntValueType<T>>; // std::conjunctionメタ関数を用いてメタ関数HasValueTypeが真のときのみ // メタ関数IntValueTypeをインスタンス化する必要がある(&&ではダメ) static_assert( IntContainer<std::list<int>>::value); static_assert(!IntContainer<std::list<char>>::value); static_assert(!IntContainer<int>::value);
// C++2a #include <concepts> template <typename T> concept IntContainer = std::same_as<typename T::value_type, int>; // T::value_typeがint以外 or 無効な場合は制約式がnot satisfiedとなる static_assert( IntContainer<std::list<int>>); static_assert(!IntContainer<std::list<char>>); static_assert(!IntContainer<int>);
ノート:制約式IntContainer<int>
の正規形はstd::same_as<typename T::value_type, int>
(T=int
)よりstd::is_same_v<T↦typename int::value_type, U↦int>
∧ std::is_same_v<T↦int, U↦typename int::value_type>
となり*1、typename int::value_type
は無効な型のため原始制約はいずれも満たされない(not satisfied)。たぶん\( 'ω' )/
C++2a DIS(N4681) 13.5.1.2/p1, p3, 13.5.3/p1-2より一部引用(下線部は強調)。
1 An atomic constraint is formed from an expression
E
and a mapping from the template parameters that appear withinE
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 (13.5.2). (snip)3 To determine if an atomic constraint is satisfied, the parameter mapping and template arguments are first substituted into its expression. If substitution results in an invalid type or expression, the constraint is not satisfied. Otherwise, the lvalue-to-rvalue conversion (7.3.1) is performed if necessary, and
E
shall be a constant expression of typebool
. The constraint is satisfied if and only if evaluation ofE
results intrue
. 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. (snip)
1 The normal form of an expression
E
is a constraint (13.5.1) that is defined as follows:
- (snip)
- The normal form of a concept-id
C<A1, A2, ..., An>
is the normal form of the constraint-expression ofC
, after substitutingA1, A2, ..., An
forC
's respective template parameters in the parameter mappings in each atomic constraint. If any such substitution results in an invalid type or expression, the program is ill-formed; no diagnostic is required. [Example:template<typename T> concept A = T::value || true; template<typename U> concept B = A<U*>; template<typename V> concept C = B<V&>;Normalization of
B
's constraint-expression is valid and results inT::value
(with the mappingT ↦ U*
) ∨true
(with an empty mapping), despite the expressionT::value
being ill-formed for a pointer typeT
. Normalization ofC
's constraint-expression results in the program being ill-formed, because it would form the invalid typeV&*
in the parameter mapping. --end example]
- The normal form of any other expression
E
is the atomic constraint whose expression isE
and whose parameter mapping is the identity mapping.2 The process of obtaining the normal form of a constraint-expression is called normalization. [Note: Normalization of constraint-expressions is performed when determining the associated constraints (13.5.1) of a declaration and when evaluating the value of an id-expression that names a concept specialization (7.5.4). --end note]
関連URL