SlideShare ist ein Scribd-Unternehmen logo
1 von 43
Concepts Lite
N3701レビュー
2013/10/26 13:30 to 18:00 に開催された、C++14勉強会 http://atnd.org/events/44249
での発表内容に、その後のフォローアップ内容を追記

SC22WG21 エキスパート
近藤 貴俊
(株式会社オージス総研)
2014/1/30

1
Concepts Liteとは
• テンプレートに制約を持たせることがで
きる機能
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3701.pdf

2014/1/30

2
Convension
class_name
function_name
new!
Constraint_name
TemplateParameter
第2区切りは出てこないかも

2014/1/30

3
制約をかける

Concepts Lite Syntax
C++11ではテンプレート引数への制約を直接表現する方法が無い
// Cont must be sortable
template<typename Cont>
void sort(Cont& container);

制約をコメントで記述

Concepts Liteの導入により、以下のように制約を記述することが可能
requires-expressionにより制約を記述

関数テンプレート

template<typename Cont>
requires Sortable<Cont>()
void sort(Cont& container);
typenameの箇所にconstraintを記述

同じ意味

template<Sortable Cont>
void sort(Cont& container);
templateの代わりにconcept-introductionを用いて記述
Sortable{Cont}
void sort(Cont& container);

2014/1/30

4
制約をかける

Concepts Lite Syntax
制約違反の際、分かりやすい診断メッセージを出力可能
list<int> lst = ...;
sort(lst); // Error

error: no matching function for call to `sort(list<int>&)'
sort(l);
^
note: candidate is:
note: template<Sortable T> void sort(T)
void sort(T t) { }
^
note: template constraints not satisfied because
note: `T' is not a/an `Sortable' type [with T = list<int>]
note: failed requirement with ('list<int>::iterator i', std::size_t n)
note:
`i[n]' is not valid syntax

2014/1/30

5
制約をかける

Concepts Lite Syntax

関数テンプレート

クラステンプレート

requires-clauseにより制約を記述
template<typename Cont>
requires Sortable<Cont>()
void sort(Cont& container);

template<typename T, typename A>
requires Object<T>() && Allocator<A>()
class vector;

typenameの箇所にconstraintを記述
template<Sortable Cont>
void sort(Cont& container);

template<Object T, Allocator A>
class vector;

templateの代わりにconcept-introductionを用いて記述
Sortable{Cont}
void sort(Cont& container);

Object{T} && Allocator{A}
class vector;

2つ以上の独立した制約がある場合、
この表記は使えない
詳細は後述

2014/1/30

6
制約をかける

Concepts Lite Syntax
クラステンプレートの部分特殊化

template<typename T, typename A>
requires Object<T>() && Allocator<A>()
class vector {

クラステンプレートのメンバ関数
vector(const T& v)
requires Copyable<T>();
void push_back(const T& x)
requires Copyable<T>();

メンバ関数テンプレート
template<Input_iterator I>
vector(I first, I last);
Forward_iterator{I}
vector(I first, I last);
};

2014/1/30

template<typename T>
struct foo;

template<typename T>
requires Cons1<T>()
struct foo { ... };
template<Cons2 T>
struct foo { ... };

Cons3{T}
struct foo { ... };
Tに関する、当該メンバ関数
独自の制約

7
表記が使えるとき使えないとき

制約をかける

テンプ
レート
パラメタ
の数

クラス
テンプレート

成約の数

単

単

requires-clause
を用いた表記

A

typenameの
constrained-parameter
を用いた表記

concept-introduction
を用いた表記

B

C

単

template <typename T>
requires Cons<T>()
name;

template<Cons T>
name;

Cons{T}
name;

複

関数
テンプレート

template <typename T>
requires Cons<T,T>()
name;

不可
template<
typemane T,
Cons<T> T>
name;

不可
Cons{T,T}
name;

無意味なので
この行は無視して良い

メンバ関数
テンプレート
クラス
テンプレートの
部分特殊化

制約
パラメタ
の数

複

単

Tが2個定義されてしまうはず

template <
typename T,
typename U
>
requires Cons<T>()
name;

template <
Cons T,
typename U
>
name;

不可

複

template <
typename T,
typename U
>
requires Cons<T,U>()
name;

template <
typename U,
Cons<U> T
>
name;

Cons{T,U}
name;

Don't
Care

template <
typename T,
typename U
>
requires
C1<T>() && C2<U>()
name;

template <
C1 T,
C2 U
>
name;

不可

における制約

Don't
Care

2014/1/30

複

残念

全てのテンプレート引数が単
一のConceptの実引数である
場合しか使えない

残念

8
表記が使えるとき使えないとき

制約をかける

テンプ
レート
パラメタ
の数

クラス
テンプレート

成約の数

単

単

制約
パラメタ
の数

A

concept-introduction
を用いた表記

B

C

単

template <typename T>
requires Cons<T>()
name;

template<Cons T>
name;

Cons{T}
name;

template <typename T>
requires Cons<T,T>()
name;

不可
template<
typemane T,
Cons<T> T>
name;

不可
Cons{T,T}
name;

単

template <
typename T,
typename U
>
requires Cons<T>()
name;

template <
Cons T,
typename U
>
name;

不可

template <
typename T,
typename U
>
requires Cons<T,U>()
name;

template <
typename U,
Cons<U> T
>
name;

Cons{T,U}
name;

メンバ関数
テンプレート
複

における制約
複

2014/1/30

typenameの
constrained-parameter
を用いた表記

複

関数
テンプレート

クラス
テンプレートの
部分特殊化

requires-clause
を用いた表記

残念

全てのテンプレート引数が単
一のConceptの実引数である
場合しか使えない

Don't
複
Don't
template <
template <
不可
残念
concept Consは2つのテンプレート引数を持つ。しかしここでは1つしか指定されていない。
Care
Care
typename T,
C1 T,
この場合、Cons<U> を partial-concept-id と呼ぶ。
typename U
C2 U
意味的には、Cons<_ , U> となり第1引数がプレースホルダーとして確保された状態となる。
>
>
これをrequiresに変換するには、
requires
name;
Cons<U> T で、Tを _ に代入し、requires Cons<T,U>() という意味になる。
C1<T>()→ Cons<_> で、_にTを代入し、requires Cons<T>() となる。
&& C2<U>()
Consの引数が1個の場合を考えてみると、Cons T
name;
この、部分適用的な機能は本当に必要だろうか?
C があれば、ほとんど事足りる気がするが。
9
制約をかける

関連するWording

PDF P46 Standard

Wording

7.1.6.5 Constrained type specifiers [dcl.spec.constrained]
The type denoted by a concept-name or partial-concept-id is a constrained placeholder
types. A constraint is formed from the application of the concept to the
placeholder type. The placeholder type is used as the first template argument
of the constraint. If the type specifier is a partial-concept-id, the specified arguments follow the placeholder type in the formed constraint. [Example:
Real y = f(x); // decltype(y) is a placeholder type,
後で説明
// constrained by Real<decltype(y)>
Same_as<T> a = f(b); // decltype(a) is a placeholder type,
// constrained by Same_as<T, decltype(a)>
— end example]
例がdecltype絡みばかりで
分かりにくい?

逆ではないか

Same_asとはいえ

2014/1/30

10
表記が使えるとき使えないとき

制約をかける

テンプレート
パラメタの数

制約
パラメタ
の数

制約の数

requires-clause
を用いた表記

A
クラス
テンプレート
のメンバ関数

2014/1/30

Don't
Care

Don't
Care

Don't
Care

void mem_fun()
requires Cons<T>();

typenameの
constrainedparameter
を用いた表記

conceptintroduction
を用いた表記

B

不可
テンプレート宣言では
ないため

C
不可
テンプレート宣言で
はないため

11
制約をかける

Corner Case?
テンプレート
パラメタの数

制約
パラメタ
の数

成約の数

requires-clause
を用いた表記

A
クラス
テンプレート
関数
テンプレート
メンバ関数
テンプレート

複

複

複

template <
typename T,
typename U
>
requires
C1<T, U>() &&
C2<U, T>()
name;

typenameの
constrainedparameter
を用いた表記
不可
template <
typename T,
C2<T> U
...
C1が書けない

conceptintroduction
を用いた表記

B

C
不可

クラス
テンプレートの
部分特殊化
における制約

2014/1/30

12
制約をかける

A

制約のかけ方まとめ

parserのカレントカーソルの
進む向きと考えると混乱する

冗長だが、全ての制約表記が可能

以前に定義されている
今後、定義されるかも
と時間軸で
とらえると分かりやすい

template <typename T, typename U>
requires Constraint1<T, U>() &&
Constraint2<U, T>()
name;

class hoge; // forward decl

Conceptの引数が1つの場合、読みやすい記述が可能

前方

template <Constraint1 T, Constraint2 U>
name;

B

後方

typedef hoge fuga;
class hoge {};

Conceptの引数の後方参照がある場合、表現できない
C

Conceptが1つで、全ての引数が制約されている場合に、読みやすい記述が可能
Constraint{T, U}
name;
制約されない引数がある場合表現できない。
Conceptが複数ある場合、表現できない

A

は B

と混ぜることができる

A

template <Constraint1 T, typename U>
requires ConstraintX<T>() && ConstraintY<U>()
name;
要確認

2014/1/30

OK

と C

は混ぜることができない

Constraint{T}
requires ConstraintX<T>()
name
13
制約のかけ方まとめ

制約をかける

A

冗長だが、全ての制約表記が可能
template <typename T, typename U>
requires Constraint1<T, U>() &&
Constraint2<U, T>()
name;

割と何でも書けそう

14 Templates [temp]

P48

template-declaration:
template < template-parameter-list > requires-clauseopt declaration
concept-introduction declaration
requires-clause:
requires-clause:
requires constant-expression
constant-expression
の誤りではないだろうか?
A template declaration with a requires-clause is a constrained template. A
requires-clause introduces template constraints in the form of a constant-expression
whose result type is bool.
A declaration introduced by a concept-introduction (14.9.5) is a constrained
template.
例えばこれは許される?
template <typename T>
true
name;
template <typename T>
is_pointer<T>::value
name;
2014/1/30

template <typename T>
requires (T a, T b) {
{ a == b } -> bool;
}
name;

全ての例が
requiresから
始まってるし

この記述方法に
ついては後述

14
制約をかける

B

制約のかけ方まとめ

Conceptの引数が1つの場合、読みやすい記述が可能
template <Constraint1 T, Constraint2 U>
name;

14.1 Template parameters [temp.param]

P48

conceptキーワードを使って定義した
concept definitionしか書けない
constexpr関数名はNG

7.1.6 Simple type specifiers [dlt.type.simple]

type-name:
...
concept-name
partial-concept-id
concept-name:
identifier
partial-concept-id:
concept-name < template-argument-list >

P46

template-parameter:
type-parameter
parameter-declaration
constrained-parameter
constrained-parameter:
constraint-id ...opt identifier
constraint-id ...opt identifier = constrained-default-argument
constraint-id:
concept-name
partial-concept-id
constrained-default-argument:
type-id
template-name

A constrained-parameter is introduced by a constraint-id, which is either a
concept-name or a partial-concept-id. The concept definition referred to by the
constraint-id determines the kind of template parameter and the constraints
applied to that argument.
P47
7.1.7 The concept specifier [dcl.concept]
The concept specifier shall be applied to only the definition of a function
template. A function template definition having the concept specifier is called a
concept definition.
2014/1/30

イタリックにすべき?

15
制約をかける

C

制約のかけ方まとめ

Conceptが1つで、全ての引数が制約されている場合に、読みやすい記述が可能
Constraint {T, U}
name;
14 Templates [temp]

conceptキーワードを使って定義した
concept definitionしか書けない
constexpr関数名はNG

P48

template-declaration:
template < template-parameter-list > requires-clauseopt declaration
concept-introduction declaration
requires-clause:
constant-expression
14.9.5 Concept Introductions [temp.con.intro]

P54

concept-introduction:
concept-name { introduced-parameter-list }
introduced-parameter-list:
identifier
introduced-parameter-list , identifier
The concept name is matched, based on the number of introduced parameters
to a corresponding concept definition. If no such concept can be found, the
program is ill-formed.
The kind of each introduced parameter (type, non-type, template), is the same
as the corresponding template parameter in the matched concept definition.
The concept is applied introduced parameters as a constraint on the trailing
declaration.

2014/1/30

イタリックにすべき?

16
制約をかける

非型パラメータの制約
template<size_t N>
concept bool Prime() { return is_prime(N); }

P29 ではconstexpr だが conceptの
誤記であろう

conceptでないと、こうは書けないはず

template<Object T, Prime N>
class hash_array;

template<typename T, size_t N>
requires Object<T>() && Prime<N>()
class hash_array;
この書き方なら constexpr でもOK

hash_array<int, 57> a; // Error 57は素数では無い

2014/1/30

17
制約をかける

Lambda

Standard Wording はまだ無い

vector<string> v = {...};
const char* str = "hello";
find_if(v, [str](const auto& x) { return str == x; });
[str](const auto& x) { return str == x; }

制約なし

[str](const String& x) { return str == x; }
B
[str]<String T>(const T& x) { return str == x; }

繰り返しStringが出てくるとき短くTで書ける

[str] String{T} (const T& x) { return str == x; }
[] Input_query{I, P} (I first, I last, P pred) { ... }
reqires表記はサポートされないため、表現能力には限界がある

struct Functor {
template <typename T, typename U>
requires Cons1<T, U>() && Cons2<U, T>()
void operator()(T, U) {}
};
例えばこれはlambdaで表現できない

conceptを新たに定義すれば書けなくはないが
2014/1/30

C

制約として書けるのは
おそらく concept definitionを満たす
constrained-parameter
現状は concept name としか書いてない P11

constrained-parameter:
constraint-id ...opt identifier
constraint-id ...opt identifier = constrained-default-argument
constraint-id:
concept-name
partial-concept-id

template <typename T, typename U>
concept bool My_constrain() {
return requires {
requires Cons1<T, U>();
requires Cons2<U, T>();
};
}
[] (My_constrain{T, U} (T, U) { ... }

18
制約をかける

Auto
autoが書けるところ全てを、conceptで置き換え可能にしようというアイデア

generic lambdaを推し進めると次のように書けるようになる?
制約あり

制約無し

auto gcd(auto a, auto b);

Integer gcd(Integer a, Integer b);
Integer制約を
かける

上記は、下記と同義

template<typename T, typename U>
auto gcd(T a, U b);

上記は、下記と同義

template<Integer T>
T gcd(T a, T b);

制約無し

template <typename T>
auto begin(T&& t) -> decltype(t.begin());

Integer制約

template <typename T>
Iterator begin(T&& t) -> decltype(t.begin());

戻り値推論で

template <typename T>
Iterator begin(T&& t);

A の書き方なら

2014/1/30

template <typename T>
requires Iterator<decltype(declval<T>().begin())>()
auto begin(T&& t);
19
制約をかける

Auto
変数も制約可能

auto y = f(x);

Real y = f(x);
Random_access_iterator r = find(p,q,v);

関数のオーバーロードセットを制約されたテンプレートに渡すことが可能

vector<double> v { ... };
Number n = accumulate(v.begin(), v.end(), operator*);

Number n = accumulate(v.begin(), v.end(), [](auto a, auto b) { return operator*(a, b)});

accumulateのテンプレートパラメタが制約されていることが必須とのこと
(詳細は不明)

2014/1/30

20
制約の内容

制約の定義(concept)

template<typename T>
concept bool Equality_comparable() { ... }

P47
7.1.7 The concept specifier [dcl.concept]
The concept specifier shall be applied to only the definition of a function template. A function template definition having the concept specifier is called a
concept definition.
Every concept definition is also a constexpr declaration (7.1.5).
Concept definitions have the following restrictions:
 The template must be unconstrained.
 The result type must be bool.
 The declaration may have no function parameters.
may?
 The declaration must be defined.
 The function shall not be recursive.

制約をconceptとして定義することで、以下の表記が可能となる
B

2014/1/30

template <Constraint1 T, Constraint2 U>
name;

C

Constraint{T, U}
name;
21
制約の内容定義

制約の内容

B

C

の表記を使わないのであれば constexpr でもよい

template<typename T>
concept bool Constraint()
{
return requires (T a, T b) {
a++;
a != b;

// simple requirement

{a == b} -> bool;
{ ++a } -> T&;
{ T(a) } noexcept constexpr;

// compound-requirement

typename T::value_type;

// type-requirement

requires Other_constraint<T>(); // nested-requirement
};
}

requres-expression

2014/1/30

22
制約の内容定義

制約の内容

template<typename T>
concept bool Constraint()
{
return requires (T a, T b) {
a++;
a != b;
{a == b} -> bool;
{ ++a } -> T&;
{ T(a) } noexcept constexpr;
typename T::value_type;

5.1.3 Requires expressions [expr.prim.requires]
A requires expression provides a concise way to express
syntactic requirements
for template constraints. [Example:
template<typename T>
constexpr bool Readable() {
かなり意味不明
return requires (T i) {
(後ほど再検討)
// simple requirement
typename Value_type<T>;
const Value_type<T>& = {*i};
};
// compound-requirement
}
— end example]

P45

// type-requirement

requires Other_constraint<T>(); // nested-requirement
};
}

2014/1/30

P45
A requires-expression shall only appear inside a template.
The type of a requires-expression is bool, and it is a constant expression.
The requires-expression may be introduce local arguments via a parameterdeclaration-clause. These parameters have no linkage, storage, or lifetime. They
are used as notation for the purpose of writing requirements.
The body of requires-expression is a list of requirements. If each requirement in
that list is satisfied, the result of the expression is true, or false otherwise.

テンプレートの中にしか書けない(テンプレートの中ならconceptの中じゃなくても書ける)
式の値の型はbool。引数は、制約記述のためにローカル変数的に用いられ、リンケージや
ライフタイムは持たない。内容は制約のリストで、全リストがtrueならrequires-expressionの値が
trueとなり、そうでなければ falseとなる。

23
制約の内容定義

制約の内容

template<typename T>
concept bool Constraint()
{
return requires (T a, T b) {
a++;
a != b;

// simple requirement

P45
5.1.3.1 Simple requirements [expr.req.simple]
{a == b} -> bool;
// compound-requirement
A simple-requirement introduces a requirement that the expression is a valid
{ ++a } -> T&
expression } noexcept constexpr; instantiation of the constraint results in
{ T(a) when instantiated. If the
a substitution failure, the the requirement is not satisfied.

typename T::value_type;

// type-requirement

requires Other_constraint<T>(); // nested-requirement
};
}

2014/1/30

24
制約の内容

制約の内容定義

P45
5.1.3.2 Compound requirements [expr.req.compound]
A compound-requirement introduces a set of requirements involving a single
template<typename T>
expression. The expression must compile when instantiated.
concept bool Constraint()
If a result-type-requirement is present then the result type of the instantiated
{
expression must satisfy that requirement. If the required type-id is a constrained
return requires (T a, those constraints must also be satisfied.
placeholder type (7.1.6.5), thenT b) {
a++;
// simple requirement
If the constexpr specifier is present, the instantiated expression must be constexpr-evaluable.
a != b;
If the noexcept specifier is present, instantiated expression must not propagate exceptions.

{a == b} -> bool;
{ ++a } -> T&;
{ T(a) } noexcept constexpr;

2014/1/30

// compound-requirement
戻り値がboolに変換可能なら制約を満たすといったケースを
satisfy that requirementでは明言できていない気がする。
that requirementはresult-type-requirementを指すはず。

7.1.6.5 Constrained type specifiers [dcl.spec.constrained]
typename T::value_type;
// type-requirement
P46
The type denoted by a concept-name or partial-concept-id is a constrained placeholder types. A
onstraint is formed from the application of the concept to the placeholder type. The placeholder type
requires Other_constraint<T>(); // nested-requirement
is used as the first template argument of the constraint. If the type specifier is a partial-concept-id, the
specified arguments follow the placeholder type in the formed constraint. [Example:
};
Real y = f(x); // decltype(y) is a placeholder type,
}
// constrained by Real<decltype(y)>
Same_as<T> a = f(b); // decltype(a) is a placeholder type,
戻り値が別のConstraind placeholder typeの場合は
// constrained by Same_as<T, decltype(a)>
ここで説明できている
— end example]
The first use of concept-name or partial-concept-id within a scope binds that name to the placeholder
type so that subsequent uses of the same name refer to the same type. [Example:
template<typename T>
concept bool Number() { ... }
auto mul = [](Number a, Number b) { return a * b; }
The types of a and b are the same. This is equivalent to having written:
auto mul = []<Number N>(N a, N b) { return a * b; }
— end example]

25
制約の内容定義

制約の内容

template<typename T>
concept bool Constraint()
{
return requires (T a, T b) {
a++;
a != b;

// simple requirement

{a == b} -> bool;
{ ++a } -> T&;
{ T(a) } noexcept constexpr;
typename T::value_type;

}

2014/1/30

// compound-requirement

// type-requirement

P45
5.1.3.3 Type requirements [expr.req.type]
requires Other_constraint<T>(); // nested-requirement
A type-requirement introduces a requirement that an associated type name can
be formed when instantiated. If the instantiation of the type requirement results
}; in a substitution failure, the requirement is not satisfied.

26
制約の内容

制約の内容定義
template<typename T>
concept bool Constraint()
{
return requires (T a, T b) {
a++;
a != b;

// simple requirement

{a == b} -> bool;
{ ++a } -> T&;
{ T(a) } noexcept constexpr;

// compound-requirement

typename T::value_type;

// type-requirement

requires Other_constraint<T>(); // nested-requirement
P46
5.1.3.4 Nested requirements [expr.req.type]
}; nested requirement introduces additional constraints to be evaluated as part
A
} of the requires expression. The requires-clause is constexpr evaluated, and the
requirement is satisfied only when that evaluation yields true.

2014/1/30

27
オーバーロードの解決
template<Container C>
void f(const C& c); // #1

template<Forward_iterator I>
void f(I i); // #1

template<typename S>
requires Container<S>() || Range<S>()
void f(const S& s); // #2

template<Random_access_iterator I>
void f(I i); // #2
...

template<Equality_comparable T>
void f(const T& x); // #3

vector<int> v { ... };
f(v.begin()) // calls #2

...
vector<int> v { ... };

list<int> l { ... };
f(l.begin()) // calls #1

f(v) // calls #1
f(filter(v, even)); // calls #2
f(0); // calls #3

2014/1/30

28
オーバーロードの解決
logical-and
&&

logical-or

concept check

||

Concept_name<T>()

左記以外の expression
atomic proposition

14.9.1 Constraint reduction [temp.con.reduce]
A constrained template’s actual constraints are reduced by inlining concept
checks, and producing an expression comprised of only atomic propositions and logical-andexpressionss and logical-or-expressions.
reduceされたイメージ

&&
&&

atomic proposition

||
atomic proposition

14.9.2 Constraint Satisfaction [temp.con.sat]
A template’s constraints are satisfied if the constexpr evaluation of the reduced
constraints results in true.

2014/1/30

P52

P52

29
オーバーロードの解決
14.5.6.2 Partial ordering of function templates [tmp.func]
Partial ordering selects which of two function templates is more specialized
than the other by transforming each template in turn (see next paragraph)
and performing template argument deduction using the function type. The
deduction process determines whether one of the templates is more specialized
than the other. If so, the more specialized template is the one chosen by the
partial ordering process. If both deductions succeed, the the more specialized
template is the one that is more constrained (14.9.3).

P51

より制約された方が、よりspecializedされたテンプレートである

2014/1/30

30
オーバーロードの解決
P53
14.9.3 Partial ordering of constraints [temp.con.ord]
Partial ordering of constraints is used to choose among ambiguous specializations during the partial ordering of
function templates, the partial ordering of class templates, and the use of template template arguments. The
partial ordering of two reduced constraints P and Q determines if P subsumes Q.
Determining the partial ordering of reduced constraints requires their decomposition into a list of lists of atomic
propositions. Decomposition of a reduced constraint P begins with a single list (the current list) containing the
reduced constraint P (the current term). Decomposition proceeds by analyzing the current
term.
 If P is of the form a && b, then replace P in the current list with the operands a and b so that a is the current
term and b will be the next term.
 If P is of the form a || b, then create a copy of the current list, replacing P with a in the original and replacing
P with b in the copy so that a is the current term in the original and b is the current term in the copy.
 Otherwise, advance to the next term. If there are no remaining terms, advance to the next list. If there are
no remaining lists, decomposition terminates.
Given two reduced constraints P and Q, then P subsumes Q only if all of Q’s atomic propositions can be found in
the P. Denote this comparison as P ⊢ Q.
This is computed by first decomposing P into a list of lists of atomic propositions, L, and then comparing the
expression Q against each list Li in L, which is equivalent to determining if Li ⊢ Q according to the following rules:
 If Q is of the form a && b, then Li ⊢ Q if and only if Li ⊢ a and Li ⊢ b.
 If Q is of the form a || b, then Li ⊢ Q if and only if Li ⊢ a or Li ⊢ b.
 Otherwise Li ⊢ Q if and only if there exist some atomic proposition A in Li that matches Q (14.9.4).
Only when each Li ⊢ Q does P ⊢ Q.
For two template declarations with equivalent type, the first is at least as constrained as the second if both
templates are unconstrained, the first is constrained and the second unconstrained, or the constraints of the first
subsume the constraints of the second.

2014/1/30

x ⊢ y means y is derivable from x.
y は x から推論できる。

31
オーバーロードの解決
A && B && C

A && B || C

&&

A || B && C

||

&&

&&

&&

A

B

A

C

B

C

||

A

B

A

C

A

B

B

A

atomic proposition の 集合 のリストを形成する

C

B

C

C

C

A || (B && C)
||

集合

A

B
&&

リスト
集合

C
A

B

B

C

C

A

2014/1/30

32
オーバーロードの解決

満たされている制約
テンプレートの制約

P

A || B

A

Q

A

P

A

A

A

B

Q

A && B

A

B

A

A

B

P

A

B

P

A

B

Q

A

B

Q

A

B

Qがより制約されている

Q は P に含まれる
P は Qに含まれない

2014/1/30

Pがより制約されている
Pを満たすなら常にQ満たす
Qを満たしてもPを満たして
いるとは限らない
P は Q に含まれる
Q は Pに含まれない

満たされている制約は候補に挙げるか否かの判断に使うだけで、
どちらがより制約されているかの判断には使わない

確信が持てない

33
オーバーロードの解決
P
A

B

C

Q

A || (B && C)

A

B

A

C

P

(A && B) || C

B

A

B

C

A && B

A

Q

C

B

C

C

A

A

P
B

C

B

A

A

Q

B

B

C

PQ同レベル
2014/1/30

C

C

PQ同レベル
34
オーバーロードの解決
P

Q

A && B || C

A && B && C

||

&&

&&

&&

A

B

A

A

C

B

B

A

B

C

C

C

満たすatomic
proposition

選択されるオーバーロード

A

-

-

B

-

-

C

P

P: P.C

AB

P

P: P.AB

BC

P

P: P.C

CA

P

P: P.C

ABC
2014/1/30

成立する
制約

P,Q

Q: Q.ABC (P.AB と P.C の両方が Q.ABCに包含される)
35
オーバーロードの解決
P

Q

(A && B&& C) || D || E

A

B

(A && B)|| C || (D && E)

C

A

D

A

C

E

D

B

B

D

E

A

C

B

E

D

C

満たすatomic
proposition

成立する
制約

選択されるオーバーロード

A

-

-

C

Q

Q

D

P

P

ABC

P,Q

両方

DE

P,Q

ABCD

P,Q

ABCDE
2014/1/30

E

P,Q

もし、非テンプレート引数のimplicit conversionが絡まなければ、
両方== 曖昧 でエラーとなる
implicit conversionが関係するケースは次ページで検討
36
オーバーロードの解決
Container ⊃ Equality_comparable
// #1
template <Container C>
void foo(C c, int i);

// #2
template <Equality_comparable Ec>
void foo(Ec ec, double d);
std::vector<int> v;
foo(v, 1);
// call #1
foo(v, 12.3); // call #1
vは#1に、よりマッチする。12.3 は #2に、よりマッチする。
今回新たに導入された制約のマッチ度合いと、これまでも存在したimplicit conversionの必要性
によるマッチ度合いがどう評価されるのか記述が見つからない。
https://groups.google.com/a/isocpp.org/forum/#!topic/concepts/67H0UOXe03g
によれば、非テンプレート引数のConversionの方が、Constraintよりも優先されるとのこと。
P293
13.3 Overload resolution [over.match]
But, once the candidate functions and argument lists have been identified, the selection of the best function
is the same in all cases:
— First, a subset of the candidate functions (those that have the proper number of arguments and meet
certain other conditions) is selected to form a set of viable functions (13.3.2).
— Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed
to match each argument to the corresponding parameter of each viable function.

2014/1/30

37
Standard Wording への指摘
5.1.3 Requires expressions [expr.prim.requires] P45
A requires expression provides a concise way to express
syntactic requirements
for template constraints. [Example:
template<typename T>
constexpr bool Readable() {
return requires (T i) {
このような表記は許されていないのでは?
typename Value_type<T>;
const Value_type<T>& = {*i};
};
}
— end example]
エスパーすると、こう書きたかったのか?
constexpr でもいいけど conceptにしない理由がない
template<typename T>
concept bool Readable() {
return requires (T i) {
typename T::value_type;
{*i} -> const typename T::value_type&;
};
}

2014/1/30

38
Standard Wording への指摘
P46
7.1.6.5 Constrained type specifiers [dcl.spec.constrained]
The type denoted by a concept-name or partial-concept-id is a constrained place-holder
types. A constraint is formed from the application of the concept to the
placeholder type. The placeholder type is used as the first template argument
of the constraint. If the type specifier is a partial-concept-id, the specified arguments follow the placeholder
type in the formed constraint. [Example:

Real y = f(x); // decltype(y) is a placeholder type,
// constrained by Real<decltype(y)>
Same_as<T> a = f(b); // decltype(a) is a placeholder type,
// constrained by Same_as<T, decltype(a)>
— end example]
逆ではないか

Same_asとはいえ

Concept_name { a, b} という表記がある今、
そもそも、この関数の部分適用みたいなの必要なの?という議論もある

2014/1/30

39
Standard Wording への指摘
P47
7.1.7 The concept specifier [dcl.concept]
The concept specifier shall be applied to only the definition of a function template. A function template definition having the concept specifier is called a
concept definition.
Every concept definition is also a constexpr declaration (7.1.5).
Concept definitions have the following restrictions:
 The template must be unconstrained.
 The result type must be bool.
shall have または must have ではないか?
 The declaration may have no function parameters.
 The declaration must be defined.
 The function shall not be recursive.

2014/1/30

40
Standard Wording への指摘
14 Templates [temp]

P48

template-declaration:
template < template-parameter-list > requires-clauseopt declaration
concept-introduction declaration
requires-clause:
requires-clause:
requires constant-expression
constant-expression
の誤りではないだろうか?

2014/1/30

41
Standard Wording への指摘
14.1 Template parameters [temp.param]

P48

template-parameter:
type-parameter
parameter-declaration
constrained-parameter
constrained-parameter:
constraint-id ...opt identifier
constraint-id ...opt identifier = constrained-default-argument
constraint-id:
concept-name partial-concept-id
constrained-default-argument:
type-id
template-name
改行が必要と思われる

2014/1/30

42
Standard Wording への指摘
14.3.3 Template template arguments [tmp.arg.template]
A template-argument matches a template template-parameter (call it P) when
each of the template parameters in the template-parameter-list of the templateargument’s
corresponding class template or alias template (call it A) matches
the corresponding template parameter in the template-parameter-list of P, and
when P is not less constrained (14.9.3) than A. [Example
// ... from standard

P50

template<template<Copyable>> class C>
class stack { ... };
template<Regular T> class list1;
template<Object T> class list1;

list2の誤りと思われる

stack<list1> s1; // OK: Regular is more constrained than Copyable
stack<list2> s2; // error: Object is not more constrained than Copyable
— end example]

14.9.5 Concept Introductions [temp.con.intro]

P54

concept-introduction:
concept-name { introduced-parameter-list }
introduced-parameter-list:
identifier introduced-parameter-list , identifier
改行が必要と思われる

2014/1/30

43

Weitere ähnliche Inhalte

Was ist angesagt?

闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみたSatoshi Sato
 
すごいConstたのしく使おう!
すごいConstたのしく使おう!すごいConstたのしく使おう!
すごいConstたのしく使おう!Akihiro Nishimura
 
Uart受信設計2013
Uart受信設計2013Uart受信設計2013
Uart受信設計2013Kiyoshi Ogawa
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?Shinichi Hirauchi
 
C#coding guideline その2_20130325
C#coding guideline その2_20130325C#coding guideline その2_20130325
C#coding guideline その2_20130325Yoshihisa Ozaki
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターンMoriharu Ohzu
 
UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張Ryota Murohoshi
 
Code Contracts in .NET 4
Code Contracts in .NET 4Code Contracts in .NET 4
Code Contracts in .NET 4信之 岩永
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26Yoshihisa Ozaki
 
テストコードの定型化
テストコードの定型化テストコードの定型化
テストコードの定型化Shinichi Hirauchi
 
言語処理系入門1
言語処理系入門1言語処理系入門1
言語処理系入門1Kenta Hattori
 
Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんかcch-robo
 
良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方Shigenori Sagawa
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ増田 亨
 
契約プログラミング
契約プログラミング契約プログラミング
契約プログラミングOda Shinsuke
 

Was ist angesagt? (20)

闇魔術を触ってみた
闇魔術を触ってみた闇魔術を触ってみた
闇魔術を触ってみた
 
Emcpp item31
Emcpp item31Emcpp item31
Emcpp item31
 
すごいConstたのしく使おう!
すごいConstたのしく使おう!すごいConstたのしく使おう!
すごいConstたのしく使おう!
 
Uart受信設計2013
Uart受信設計2013Uart受信設計2013
Uart受信設計2013
 
C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?C# から java へのプログラム移植で体験したtddの効果は?
C# から java へのプログラム移植で体験したtddの効果は?
 
C#coding guideline その2_20130325
C#coding guideline その2_20130325C#coding guideline その2_20130325
C#coding guideline その2_20130325
 
クロージャデザインパターン
クロージャデザインパターンクロージャデザインパターン
クロージャデザインパターン
 
Boost Fusion Library
Boost Fusion LibraryBoost Fusion Library
Boost Fusion Library
 
UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張UnityでC#を勉強しはじめた私の主張
UnityでC#を勉強しはじめた私の主張
 
Code Contracts in .NET 4
Code Contracts in .NET 4Code Contracts in .NET 4
Code Contracts in .NET 4
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26
 
テストコードの定型化
テストコードの定型化テストコードの定型化
テストコードの定型化
 
Xtext入門
Xtext入門Xtext入門
Xtext入門
 
言語処理系入門1
言語処理系入門1言語処理系入門1
言語処理系入門1
 
Java class design
Java class designJava class design
Java class design
 
Flutterを体験してみませんか
Flutterを体験してみませんかFlutterを体験してみませんか
Flutterを体験してみませんか
 
良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方良い?悪い?コードコメントの書き方
良い?悪い?コードコメントの書き方
 
オブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツオブジェクト指向の設計と実装の学び方のコツ
オブジェクト指向の設計と実装の学び方のコツ
 
契約プログラミング
契約プログラミング契約プログラミング
契約プログラミング
 
C++0x concept
C++0x conceptC++0x concept
C++0x concept
 

Andere mochten auch

Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02Takatoshi Kondo
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Takatoshi Kondo
 
Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02Takatoshi Kondo
 
MessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization LibraryMessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization LibraryTakatoshi Kondo
 
Pub/Sub model, msm, and asio
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asioTakatoshi Kondo
 
CppCon2016 report and Boost.SML
CppCon2016 report and Boost.SMLCppCon2016 report and Boost.SML
CppCon2016 report and Boost.SMLTakatoshi Kondo
 

Andere mochten auch (9)

Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02Boostsapporomsmpost 111106070819-phpapp02
Boostsapporomsmpost 111106070819-phpapp02
 
Effective Modern C++ study group Item39
Effective Modern C++ study group Item39Effective Modern C++ study group Item39
Effective Modern C++ study group Item39
 
Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02Boostsapporomsmpre 111030054504-phpapp02
Boostsapporomsmpre 111030054504-phpapp02
 
N3495 inplace realloc
N3495 inplace reallocN3495 inplace realloc
N3495 inplace realloc
 
Boost sg msgpack
Boost sg msgpackBoost sg msgpack
Boost sg msgpack
 
MessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization LibraryMessagePack(msgpack): Compact and Fast Serialization Library
MessagePack(msgpack): Compact and Fast Serialization Library
 
Pub/Sub model, msm, and asio
Pub/Sub model, msm, and asioPub/Sub model, msm, and asio
Pub/Sub model, msm, and asio
 
Emcpp0506
Emcpp0506Emcpp0506
Emcpp0506
 
CppCon2016 report and Boost.SML
CppCon2016 report and Boost.SMLCppCon2016 report and Boost.SML
CppCon2016 report and Boost.SML
 

Ähnlich wie N3701 concept lite

Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweightgintenlabo
 
C++14 variable templates
C++14 variable templatesC++14 variable templates
C++14 variable templatesAkira Takahashi
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会Akihiko Matuura
 
constexpr idioms
constexpr idiomsconstexpr idioms
constexpr idiomsfimbul
 
C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編道化師 堂華
 

Ähnlich wie N3701 concept lite (7)

What is template
What is templateWhat is template
What is template
 
Boost.Flyweight
Boost.FlyweightBoost.Flyweight
Boost.Flyweight
 
C++14 variable templates
C++14 variable templatesC++14 variable templates
C++14 variable templates
 
C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会C++ Template Meta Programming の紹介@社内勉強会
C++ Template Meta Programming の紹介@社内勉強会
 
constexpr idioms
constexpr idiomsconstexpr idioms
constexpr idioms
 
C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編C++ tips 3 カンマ演算子編
C++ tips 3 カンマ演算子編
 
C++ tips4 cv修飾編
C++ tips4 cv修飾編C++ tips4 cv修飾編
C++ tips4 cv修飾編
 

Kürzlich hochgeladen

UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 

Kürzlich hochgeladen (9)

UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 

N3701 concept lite

  • 1. Concepts Lite N3701レビュー 2013/10/26 13:30 to 18:00 に開催された、C++14勉強会 http://atnd.org/events/44249 での発表内容に、その後のフォローアップ内容を追記 SC22WG21 エキスパート 近藤 貴俊 (株式会社オージス総研) 2014/1/30 1
  • 4. 制約をかける Concepts Lite Syntax C++11ではテンプレート引数への制約を直接表現する方法が無い // Cont must be sortable template<typename Cont> void sort(Cont& container); 制約をコメントで記述 Concepts Liteの導入により、以下のように制約を記述することが可能 requires-expressionにより制約を記述 関数テンプレート template<typename Cont> requires Sortable<Cont>() void sort(Cont& container); typenameの箇所にconstraintを記述 同じ意味 template<Sortable Cont> void sort(Cont& container); templateの代わりにconcept-introductionを用いて記述 Sortable{Cont} void sort(Cont& container); 2014/1/30 4
  • 5. 制約をかける Concepts Lite Syntax 制約違反の際、分かりやすい診断メッセージを出力可能 list<int> lst = ...; sort(lst); // Error error: no matching function for call to `sort(list<int>&)' sort(l); ^ note: candidate is: note: template<Sortable T> void sort(T) void sort(T t) { } ^ note: template constraints not satisfied because note: `T' is not a/an `Sortable' type [with T = list<int>] note: failed requirement with ('list<int>::iterator i', std::size_t n) note: `i[n]' is not valid syntax 2014/1/30 5
  • 6. 制約をかける Concepts Lite Syntax 関数テンプレート クラステンプレート requires-clauseにより制約を記述 template<typename Cont> requires Sortable<Cont>() void sort(Cont& container); template<typename T, typename A> requires Object<T>() && Allocator<A>() class vector; typenameの箇所にconstraintを記述 template<Sortable Cont> void sort(Cont& container); template<Object T, Allocator A> class vector; templateの代わりにconcept-introductionを用いて記述 Sortable{Cont} void sort(Cont& container); Object{T} && Allocator{A} class vector; 2つ以上の独立した制約がある場合、 この表記は使えない 詳細は後述 2014/1/30 6
  • 7. 制約をかける Concepts Lite Syntax クラステンプレートの部分特殊化 template<typename T, typename A> requires Object<T>() && Allocator<A>() class vector { クラステンプレートのメンバ関数 vector(const T& v) requires Copyable<T>(); void push_back(const T& x) requires Copyable<T>(); メンバ関数テンプレート template<Input_iterator I> vector(I first, I last); Forward_iterator{I} vector(I first, I last); }; 2014/1/30 template<typename T> struct foo; template<typename T> requires Cons1<T>() struct foo { ... }; template<Cons2 T> struct foo { ... }; Cons3{T} struct foo { ... }; Tに関する、当該メンバ関数 独自の制約 7
  • 8. 表記が使えるとき使えないとき 制約をかける テンプ レート パラメタ の数 クラス テンプレート 成約の数 単 単 requires-clause を用いた表記 A typenameの constrained-parameter を用いた表記 concept-introduction を用いた表記 B C 単 template <typename T> requires Cons<T>() name; template<Cons T> name; Cons{T} name; 複 関数 テンプレート template <typename T> requires Cons<T,T>() name; 不可 template< typemane T, Cons<T> T> name; 不可 Cons{T,T} name; 無意味なので この行は無視して良い メンバ関数 テンプレート クラス テンプレートの 部分特殊化 制約 パラメタ の数 複 単 Tが2個定義されてしまうはず template < typename T, typename U > requires Cons<T>() name; template < Cons T, typename U > name; 不可 複 template < typename T, typename U > requires Cons<T,U>() name; template < typename U, Cons<U> T > name; Cons{T,U} name; Don't Care template < typename T, typename U > requires C1<T>() && C2<U>() name; template < C1 T, C2 U > name; 不可 における制約 Don't Care 2014/1/30 複 残念 全てのテンプレート引数が単 一のConceptの実引数である 場合しか使えない 残念 8
  • 9. 表記が使えるとき使えないとき 制約をかける テンプ レート パラメタ の数 クラス テンプレート 成約の数 単 単 制約 パラメタ の数 A concept-introduction を用いた表記 B C 単 template <typename T> requires Cons<T>() name; template<Cons T> name; Cons{T} name; template <typename T> requires Cons<T,T>() name; 不可 template< typemane T, Cons<T> T> name; 不可 Cons{T,T} name; 単 template < typename T, typename U > requires Cons<T>() name; template < Cons T, typename U > name; 不可 template < typename T, typename U > requires Cons<T,U>() name; template < typename U, Cons<U> T > name; Cons{T,U} name; メンバ関数 テンプレート 複 における制約 複 2014/1/30 typenameの constrained-parameter を用いた表記 複 関数 テンプレート クラス テンプレートの 部分特殊化 requires-clause を用いた表記 残念 全てのテンプレート引数が単 一のConceptの実引数である 場合しか使えない Don't 複 Don't template < template < 不可 残念 concept Consは2つのテンプレート引数を持つ。しかしここでは1つしか指定されていない。 Care Care typename T, C1 T, この場合、Cons<U> を partial-concept-id と呼ぶ。 typename U C2 U 意味的には、Cons<_ , U> となり第1引数がプレースホルダーとして確保された状態となる。 > > これをrequiresに変換するには、 requires name; Cons<U> T で、Tを _ に代入し、requires Cons<T,U>() という意味になる。 C1<T>()→ Cons<_> で、_にTを代入し、requires Cons<T>() となる。 && C2<U>() Consの引数が1個の場合を考えてみると、Cons T name; この、部分適用的な機能は本当に必要だろうか? C があれば、ほとんど事足りる気がするが。 9
  • 10. 制約をかける 関連するWording PDF P46 Standard Wording 7.1.6.5 Constrained type specifiers [dcl.spec.constrained] The type denoted by a concept-name or partial-concept-id is a constrained placeholder types. A constraint is formed from the application of the concept to the placeholder type. The placeholder type is used as the first template argument of the constraint. If the type specifier is a partial-concept-id, the specified arguments follow the placeholder type in the formed constraint. [Example: Real y = f(x); // decltype(y) is a placeholder type, 後で説明 // constrained by Real<decltype(y)> Same_as<T> a = f(b); // decltype(a) is a placeholder type, // constrained by Same_as<T, decltype(a)> — end example] 例がdecltype絡みばかりで 分かりにくい? 逆ではないか Same_asとはいえ 2014/1/30 10
  • 12. 制約をかける Corner Case? テンプレート パラメタの数 制約 パラメタ の数 成約の数 requires-clause を用いた表記 A クラス テンプレート 関数 テンプレート メンバ関数 テンプレート 複 複 複 template < typename T, typename U > requires C1<T, U>() && C2<U, T>() name; typenameの constrainedparameter を用いた表記 不可 template < typename T, C2<T> U ... C1が書けない conceptintroduction を用いた表記 B C 不可 クラス テンプレートの 部分特殊化 における制約 2014/1/30 12
  • 13. 制約をかける A 制約のかけ方まとめ parserのカレントカーソルの 進む向きと考えると混乱する 冗長だが、全ての制約表記が可能 以前に定義されている 今後、定義されるかも と時間軸で とらえると分かりやすい template <typename T, typename U> requires Constraint1<T, U>() && Constraint2<U, T>() name; class hoge; // forward decl Conceptの引数が1つの場合、読みやすい記述が可能 前方 template <Constraint1 T, Constraint2 U> name; B 後方 typedef hoge fuga; class hoge {}; Conceptの引数の後方参照がある場合、表現できない C Conceptが1つで、全ての引数が制約されている場合に、読みやすい記述が可能 Constraint{T, U} name; 制約されない引数がある場合表現できない。 Conceptが複数ある場合、表現できない A は B と混ぜることができる A template <Constraint1 T, typename U> requires ConstraintX<T>() && ConstraintY<U>() name; 要確認 2014/1/30 OK と C は混ぜることができない Constraint{T} requires ConstraintX<T>() name 13
  • 14. 制約のかけ方まとめ 制約をかける A 冗長だが、全ての制約表記が可能 template <typename T, typename U> requires Constraint1<T, U>() && Constraint2<U, T>() name; 割と何でも書けそう 14 Templates [temp] P48 template-declaration: template < template-parameter-list > requires-clauseopt declaration concept-introduction declaration requires-clause: requires-clause: requires constant-expression constant-expression の誤りではないだろうか? A template declaration with a requires-clause is a constrained template. A requires-clause introduces template constraints in the form of a constant-expression whose result type is bool. A declaration introduced by a concept-introduction (14.9.5) is a constrained template. 例えばこれは許される? template <typename T> true name; template <typename T> is_pointer<T>::value name; 2014/1/30 template <typename T> requires (T a, T b) { { a == b } -> bool; } name; 全ての例が requiresから 始まってるし この記述方法に ついては後述 14
  • 15. 制約をかける B 制約のかけ方まとめ Conceptの引数が1つの場合、読みやすい記述が可能 template <Constraint1 T, Constraint2 U> name; 14.1 Template parameters [temp.param] P48 conceptキーワードを使って定義した concept definitionしか書けない constexpr関数名はNG 7.1.6 Simple type specifiers [dlt.type.simple] type-name: ... concept-name partial-concept-id concept-name: identifier partial-concept-id: concept-name < template-argument-list > P46 template-parameter: type-parameter parameter-declaration constrained-parameter constrained-parameter: constraint-id ...opt identifier constraint-id ...opt identifier = constrained-default-argument constraint-id: concept-name partial-concept-id constrained-default-argument: type-id template-name A constrained-parameter is introduced by a constraint-id, which is either a concept-name or a partial-concept-id. The concept definition referred to by the constraint-id determines the kind of template parameter and the constraints applied to that argument. P47 7.1.7 The concept specifier [dcl.concept] The concept specifier shall be applied to only the definition of a function template. A function template definition having the concept specifier is called a concept definition. 2014/1/30 イタリックにすべき? 15
  • 16. 制約をかける C 制約のかけ方まとめ Conceptが1つで、全ての引数が制約されている場合に、読みやすい記述が可能 Constraint {T, U} name; 14 Templates [temp] conceptキーワードを使って定義した concept definitionしか書けない constexpr関数名はNG P48 template-declaration: template < template-parameter-list > requires-clauseopt declaration concept-introduction declaration requires-clause: constant-expression 14.9.5 Concept Introductions [temp.con.intro] P54 concept-introduction: concept-name { introduced-parameter-list } introduced-parameter-list: identifier introduced-parameter-list , identifier The concept name is matched, based on the number of introduced parameters to a corresponding concept definition. If no such concept can be found, the program is ill-formed. The kind of each introduced parameter (type, non-type, template), is the same as the corresponding template parameter in the matched concept definition. The concept is applied introduced parameters as a constraint on the trailing declaration. 2014/1/30 イタリックにすべき? 16
  • 17. 制約をかける 非型パラメータの制約 template<size_t N> concept bool Prime() { return is_prime(N); } P29 ではconstexpr だが conceptの 誤記であろう conceptでないと、こうは書けないはず template<Object T, Prime N> class hash_array; template<typename T, size_t N> requires Object<T>() && Prime<N>() class hash_array; この書き方なら constexpr でもOK hash_array<int, 57> a; // Error 57は素数では無い 2014/1/30 17
  • 18. 制約をかける Lambda Standard Wording はまだ無い vector<string> v = {...}; const char* str = "hello"; find_if(v, [str](const auto& x) { return str == x; }); [str](const auto& x) { return str == x; } 制約なし [str](const String& x) { return str == x; } B [str]<String T>(const T& x) { return str == x; } 繰り返しStringが出てくるとき短くTで書ける [str] String{T} (const T& x) { return str == x; } [] Input_query{I, P} (I first, I last, P pred) { ... } reqires表記はサポートされないため、表現能力には限界がある struct Functor { template <typename T, typename U> requires Cons1<T, U>() && Cons2<U, T>() void operator()(T, U) {} }; 例えばこれはlambdaで表現できない conceptを新たに定義すれば書けなくはないが 2014/1/30 C 制約として書けるのは おそらく concept definitionを満たす constrained-parameter 現状は concept name としか書いてない P11 constrained-parameter: constraint-id ...opt identifier constraint-id ...opt identifier = constrained-default-argument constraint-id: concept-name partial-concept-id template <typename T, typename U> concept bool My_constrain() { return requires { requires Cons1<T, U>(); requires Cons2<U, T>(); }; } [] (My_constrain{T, U} (T, U) { ... } 18
  • 19. 制約をかける Auto autoが書けるところ全てを、conceptで置き換え可能にしようというアイデア generic lambdaを推し進めると次のように書けるようになる? 制約あり 制約無し auto gcd(auto a, auto b); Integer gcd(Integer a, Integer b); Integer制約を かける 上記は、下記と同義 template<typename T, typename U> auto gcd(T a, U b); 上記は、下記と同義 template<Integer T> T gcd(T a, T b); 制約無し template <typename T> auto begin(T&& t) -> decltype(t.begin()); Integer制約 template <typename T> Iterator begin(T&& t) -> decltype(t.begin()); 戻り値推論で template <typename T> Iterator begin(T&& t); A の書き方なら 2014/1/30 template <typename T> requires Iterator<decltype(declval<T>().begin())>() auto begin(T&& t); 19
  • 20. 制約をかける Auto 変数も制約可能 auto y = f(x); Real y = f(x); Random_access_iterator r = find(p,q,v); 関数のオーバーロードセットを制約されたテンプレートに渡すことが可能 vector<double> v { ... }; Number n = accumulate(v.begin(), v.end(), operator*); Number n = accumulate(v.begin(), v.end(), [](auto a, auto b) { return operator*(a, b)}); accumulateのテンプレートパラメタが制約されていることが必須とのこと (詳細は不明) 2014/1/30 20
  • 21. 制約の内容 制約の定義(concept) template<typename T> concept bool Equality_comparable() { ... } P47 7.1.7 The concept specifier [dcl.concept] The concept specifier shall be applied to only the definition of a function template. A function template definition having the concept specifier is called a concept definition. Every concept definition is also a constexpr declaration (7.1.5). Concept definitions have the following restrictions:  The template must be unconstrained.  The result type must be bool.  The declaration may have no function parameters. may?  The declaration must be defined.  The function shall not be recursive. 制約をconceptとして定義することで、以下の表記が可能となる B 2014/1/30 template <Constraint1 T, Constraint2 U> name; C Constraint{T, U} name; 21
  • 22. 制約の内容定義 制約の内容 B C の表記を使わないのであれば constexpr でもよい template<typename T> concept bool Constraint() { return requires (T a, T b) { a++; a != b; // simple requirement {a == b} -> bool; { ++a } -> T&; { T(a) } noexcept constexpr; // compound-requirement typename T::value_type; // type-requirement requires Other_constraint<T>(); // nested-requirement }; } requres-expression 2014/1/30 22
  • 23. 制約の内容定義 制約の内容 template<typename T> concept bool Constraint() { return requires (T a, T b) { a++; a != b; {a == b} -> bool; { ++a } -> T&; { T(a) } noexcept constexpr; typename T::value_type; 5.1.3 Requires expressions [expr.prim.requires] A requires expression provides a concise way to express syntactic requirements for template constraints. [Example: template<typename T> constexpr bool Readable() { かなり意味不明 return requires (T i) { (後ほど再検討) // simple requirement typename Value_type<T>; const Value_type<T>& = {*i}; }; // compound-requirement } — end example] P45 // type-requirement requires Other_constraint<T>(); // nested-requirement }; } 2014/1/30 P45 A requires-expression shall only appear inside a template. The type of a requires-expression is bool, and it is a constant expression. The requires-expression may be introduce local arguments via a parameterdeclaration-clause. These parameters have no linkage, storage, or lifetime. They are used as notation for the purpose of writing requirements. The body of requires-expression is a list of requirements. If each requirement in that list is satisfied, the result of the expression is true, or false otherwise. テンプレートの中にしか書けない(テンプレートの中ならconceptの中じゃなくても書ける) 式の値の型はbool。引数は、制約記述のためにローカル変数的に用いられ、リンケージや ライフタイムは持たない。内容は制約のリストで、全リストがtrueならrequires-expressionの値が trueとなり、そうでなければ falseとなる。 23
  • 24. 制約の内容定義 制約の内容 template<typename T> concept bool Constraint() { return requires (T a, T b) { a++; a != b; // simple requirement P45 5.1.3.1 Simple requirements [expr.req.simple] {a == b} -> bool; // compound-requirement A simple-requirement introduces a requirement that the expression is a valid { ++a } -> T& expression } noexcept constexpr; instantiation of the constraint results in { T(a) when instantiated. If the a substitution failure, the the requirement is not satisfied. typename T::value_type; // type-requirement requires Other_constraint<T>(); // nested-requirement }; } 2014/1/30 24
  • 25. 制約の内容 制約の内容定義 P45 5.1.3.2 Compound requirements [expr.req.compound] A compound-requirement introduces a set of requirements involving a single template<typename T> expression. The expression must compile when instantiated. concept bool Constraint() If a result-type-requirement is present then the result type of the instantiated { expression must satisfy that requirement. If the required type-id is a constrained return requires (T a, those constraints must also be satisfied. placeholder type (7.1.6.5), thenT b) { a++; // simple requirement If the constexpr specifier is present, the instantiated expression must be constexpr-evaluable. a != b; If the noexcept specifier is present, instantiated expression must not propagate exceptions. {a == b} -> bool; { ++a } -> T&; { T(a) } noexcept constexpr; 2014/1/30 // compound-requirement 戻り値がboolに変換可能なら制約を満たすといったケースを satisfy that requirementでは明言できていない気がする。 that requirementはresult-type-requirementを指すはず。 7.1.6.5 Constrained type specifiers [dcl.spec.constrained] typename T::value_type; // type-requirement P46 The type denoted by a concept-name or partial-concept-id is a constrained placeholder types. A onstraint is formed from the application of the concept to the placeholder type. The placeholder type requires Other_constraint<T>(); // nested-requirement is used as the first template argument of the constraint. If the type specifier is a partial-concept-id, the specified arguments follow the placeholder type in the formed constraint. [Example: }; Real y = f(x); // decltype(y) is a placeholder type, } // constrained by Real<decltype(y)> Same_as<T> a = f(b); // decltype(a) is a placeholder type, 戻り値が別のConstraind placeholder typeの場合は // constrained by Same_as<T, decltype(a)> ここで説明できている — end example] The first use of concept-name or partial-concept-id within a scope binds that name to the placeholder type so that subsequent uses of the same name refer to the same type. [Example: template<typename T> concept bool Number() { ... } auto mul = [](Number a, Number b) { return a * b; } The types of a and b are the same. This is equivalent to having written: auto mul = []<Number N>(N a, N b) { return a * b; } — end example] 25
  • 26. 制約の内容定義 制約の内容 template<typename T> concept bool Constraint() { return requires (T a, T b) { a++; a != b; // simple requirement {a == b} -> bool; { ++a } -> T&; { T(a) } noexcept constexpr; typename T::value_type; } 2014/1/30 // compound-requirement // type-requirement P45 5.1.3.3 Type requirements [expr.req.type] requires Other_constraint<T>(); // nested-requirement A type-requirement introduces a requirement that an associated type name can be formed when instantiated. If the instantiation of the type requirement results }; in a substitution failure, the requirement is not satisfied. 26
  • 27. 制約の内容 制約の内容定義 template<typename T> concept bool Constraint() { return requires (T a, T b) { a++; a != b; // simple requirement {a == b} -> bool; { ++a } -> T&; { T(a) } noexcept constexpr; // compound-requirement typename T::value_type; // type-requirement requires Other_constraint<T>(); // nested-requirement P46 5.1.3.4 Nested requirements [expr.req.type] }; nested requirement introduces additional constraints to be evaluated as part A } of the requires expression. The requires-clause is constexpr evaluated, and the requirement is satisfied only when that evaluation yields true. 2014/1/30 27
  • 28. オーバーロードの解決 template<Container C> void f(const C& c); // #1 template<Forward_iterator I> void f(I i); // #1 template<typename S> requires Container<S>() || Range<S>() void f(const S& s); // #2 template<Random_access_iterator I> void f(I i); // #2 ... template<Equality_comparable T> void f(const T& x); // #3 vector<int> v { ... }; f(v.begin()) // calls #2 ... vector<int> v { ... }; list<int> l { ... }; f(l.begin()) // calls #1 f(v) // calls #1 f(filter(v, even)); // calls #2 f(0); // calls #3 2014/1/30 28
  • 29. オーバーロードの解決 logical-and && logical-or concept check || Concept_name<T>() 左記以外の expression atomic proposition 14.9.1 Constraint reduction [temp.con.reduce] A constrained template’s actual constraints are reduced by inlining concept checks, and producing an expression comprised of only atomic propositions and logical-andexpressionss and logical-or-expressions. reduceされたイメージ && && atomic proposition || atomic proposition 14.9.2 Constraint Satisfaction [temp.con.sat] A template’s constraints are satisfied if the constexpr evaluation of the reduced constraints results in true. 2014/1/30 P52 P52 29
  • 30. オーバーロードの解決 14.5.6.2 Partial ordering of function templates [tmp.func] Partial ordering selects which of two function templates is more specialized than the other by transforming each template in turn (see next paragraph) and performing template argument deduction using the function type. The deduction process determines whether one of the templates is more specialized than the other. If so, the more specialized template is the one chosen by the partial ordering process. If both deductions succeed, the the more specialized template is the one that is more constrained (14.9.3). P51 より制約された方が、よりspecializedされたテンプレートである 2014/1/30 30
  • 31. オーバーロードの解決 P53 14.9.3 Partial ordering of constraints [temp.con.ord] Partial ordering of constraints is used to choose among ambiguous specializations during the partial ordering of function templates, the partial ordering of class templates, and the use of template template arguments. The partial ordering of two reduced constraints P and Q determines if P subsumes Q. Determining the partial ordering of reduced constraints requires their decomposition into a list of lists of atomic propositions. Decomposition of a reduced constraint P begins with a single list (the current list) containing the reduced constraint P (the current term). Decomposition proceeds by analyzing the current term.  If P is of the form a && b, then replace P in the current list with the operands a and b so that a is the current term and b will be the next term.  If P is of the form a || b, then create a copy of the current list, replacing P with a in the original and replacing P with b in the copy so that a is the current term in the original and b is the current term in the copy.  Otherwise, advance to the next term. If there are no remaining terms, advance to the next list. If there are no remaining lists, decomposition terminates. Given two reduced constraints P and Q, then P subsumes Q only if all of Q’s atomic propositions can be found in the P. Denote this comparison as P ⊢ Q. This is computed by first decomposing P into a list of lists of atomic propositions, L, and then comparing the expression Q against each list Li in L, which is equivalent to determining if Li ⊢ Q according to the following rules:  If Q is of the form a && b, then Li ⊢ Q if and only if Li ⊢ a and Li ⊢ b.  If Q is of the form a || b, then Li ⊢ Q if and only if Li ⊢ a or Li ⊢ b.  Otherwise Li ⊢ Q if and only if there exist some atomic proposition A in Li that matches Q (14.9.4). Only when each Li ⊢ Q does P ⊢ Q. For two template declarations with equivalent type, the first is at least as constrained as the second if both templates are unconstrained, the first is constrained and the second unconstrained, or the constraints of the first subsume the constraints of the second. 2014/1/30 x ⊢ y means y is derivable from x. y は x から推論できる。 31
  • 32. オーバーロードの解決 A && B && C A && B || C && A || B && C || && && && A B A C B C || A B A C A B B A atomic proposition の 集合 のリストを形成する C B C C C A || (B && C) || 集合 A B && リスト 集合 C A B B C C A 2014/1/30 32
  • 33. オーバーロードの解決 満たされている制約 テンプレートの制約 P A || B A Q A P A A A B Q A && B A B A A B P A B P A B Q A B Q A B Qがより制約されている Q は P に含まれる P は Qに含まれない 2014/1/30 Pがより制約されている Pを満たすなら常にQ満たす Qを満たしてもPを満たして いるとは限らない P は Q に含まれる Q は Pに含まれない 満たされている制約は候補に挙げるか否かの判断に使うだけで、 どちらがより制約されているかの判断には使わない 確信が持てない 33
  • 34. オーバーロードの解決 P A B C Q A || (B && C) A B A C P (A && B) || C B A B C A && B A Q C B C C A A P B C B A A Q B B C PQ同レベル 2014/1/30 C C PQ同レベル 34
  • 35. オーバーロードの解決 P Q A && B || C A && B && C || && && && A B A A C B B A B C C C 満たすatomic proposition 選択されるオーバーロード A - - B - - C P P: P.C AB P P: P.AB BC P P: P.C CA P P: P.C ABC 2014/1/30 成立する 制約 P,Q Q: Q.ABC (P.AB と P.C の両方が Q.ABCに包含される) 35
  • 36. オーバーロードの解決 P Q (A && B&& C) || D || E A B (A && B)|| C || (D && E) C A D A C E D B B D E A C B E D C 満たすatomic proposition 成立する 制約 選択されるオーバーロード A - - C Q Q D P P ABC P,Q 両方 DE P,Q ABCD P,Q ABCDE 2014/1/30 E P,Q もし、非テンプレート引数のimplicit conversionが絡まなければ、 両方== 曖昧 でエラーとなる implicit conversionが関係するケースは次ページで検討 36
  • 37. オーバーロードの解決 Container ⊃ Equality_comparable // #1 template <Container C> void foo(C c, int i); // #2 template <Equality_comparable Ec> void foo(Ec ec, double d); std::vector<int> v; foo(v, 1); // call #1 foo(v, 12.3); // call #1 vは#1に、よりマッチする。12.3 は #2に、よりマッチする。 今回新たに導入された制約のマッチ度合いと、これまでも存在したimplicit conversionの必要性 によるマッチ度合いがどう評価されるのか記述が見つからない。 https://groups.google.com/a/isocpp.org/forum/#!topic/concepts/67H0UOXe03g によれば、非テンプレート引数のConversionの方が、Constraintよりも優先されるとのこと。 P293 13.3 Overload resolution [over.match] But, once the candidate functions and argument lists have been identified, the selection of the best function is the same in all cases: — First, a subset of the candidate functions (those that have the proper number of arguments and meet certain other conditions) is selected to form a set of viable functions (13.3.2). — Then the best viable function is selected based on the implicit conversion sequences (13.3.3.1) needed to match each argument to the corresponding parameter of each viable function. 2014/1/30 37
  • 38. Standard Wording への指摘 5.1.3 Requires expressions [expr.prim.requires] P45 A requires expression provides a concise way to express syntactic requirements for template constraints. [Example: template<typename T> constexpr bool Readable() { return requires (T i) { このような表記は許されていないのでは? typename Value_type<T>; const Value_type<T>& = {*i}; }; } — end example] エスパーすると、こう書きたかったのか? constexpr でもいいけど conceptにしない理由がない template<typename T> concept bool Readable() { return requires (T i) { typename T::value_type; {*i} -> const typename T::value_type&; }; } 2014/1/30 38
  • 39. Standard Wording への指摘 P46 7.1.6.5 Constrained type specifiers [dcl.spec.constrained] The type denoted by a concept-name or partial-concept-id is a constrained place-holder types. A constraint is formed from the application of the concept to the placeholder type. The placeholder type is used as the first template argument of the constraint. If the type specifier is a partial-concept-id, the specified arguments follow the placeholder type in the formed constraint. [Example: Real y = f(x); // decltype(y) is a placeholder type, // constrained by Real<decltype(y)> Same_as<T> a = f(b); // decltype(a) is a placeholder type, // constrained by Same_as<T, decltype(a)> — end example] 逆ではないか Same_asとはいえ Concept_name { a, b} という表記がある今、 そもそも、この関数の部分適用みたいなの必要なの?という議論もある 2014/1/30 39
  • 40. Standard Wording への指摘 P47 7.1.7 The concept specifier [dcl.concept] The concept specifier shall be applied to only the definition of a function template. A function template definition having the concept specifier is called a concept definition. Every concept definition is also a constexpr declaration (7.1.5). Concept definitions have the following restrictions:  The template must be unconstrained.  The result type must be bool. shall have または must have ではないか?  The declaration may have no function parameters.  The declaration must be defined.  The function shall not be recursive. 2014/1/30 40
  • 41. Standard Wording への指摘 14 Templates [temp] P48 template-declaration: template < template-parameter-list > requires-clauseopt declaration concept-introduction declaration requires-clause: requires-clause: requires constant-expression constant-expression の誤りではないだろうか? 2014/1/30 41
  • 42. Standard Wording への指摘 14.1 Template parameters [temp.param] P48 template-parameter: type-parameter parameter-declaration constrained-parameter constrained-parameter: constraint-id ...opt identifier constraint-id ...opt identifier = constrained-default-argument constraint-id: concept-name partial-concept-id constrained-default-argument: type-id template-name 改行が必要と思われる 2014/1/30 42
  • 43. Standard Wording への指摘 14.3.3 Template template arguments [tmp.arg.template] A template-argument matches a template template-parameter (call it P) when each of the template parameters in the template-parameter-list of the templateargument’s corresponding class template or alias template (call it A) matches the corresponding template parameter in the template-parameter-list of P, and when P is not less constrained (14.9.3) than A. [Example // ... from standard P50 template<template<Copyable>> class C> class stack { ... }; template<Regular T> class list1; template<Object T> class list1; list2の誤りと思われる stack<list1> s1; // OK: Regular is more constrained than Copyable stack<list2> s2; // error: Object is not more constrained than Copyable — end example] 14.9.5 Concept Introductions [temp.con.intro] P54 concept-introduction: concept-name { introduced-parameter-list } introduced-parameter-list: identifier introduced-parameter-list , identifier 改行が必要と思われる 2014/1/30 43