template meta programming入門から応用まで

417
Template Meta Programming 入門から応用まで @fimbul11 2013/09/28 C++勉強会 @ tkb #2

Upload: yoshihikoozaki5

Post on 31-May-2015

6.076 views

Category:

Documents


2 download

TRANSCRIPT

Page 1: Template Meta Programming入門から応用まで

Template Meta Programming入門から応用まで

@fimbul11

2013/09/28 C++勉強会 @ tkb #2

Page 2: Template Meta Programming入門から応用まで

自己紹介

twitter : @fimbul11github : fimbul

University of Tsukuba B3 専攻 : 情報とメディア技術(mast)

プログラミングとかやってます、歴は2年ちょっとぐらいですC++とかやってます、歴は1年半ぐらいですペン回しとか出来ます、歴は7年ぐらいです

Page 3: Template Meta Programming入門から応用まで

このような無名の勉強会に遠方からも多くの人に来ていただけました、本当にありがとうございます

はじめに

Page 4: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 5: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 6: Template Meta Programming入門から応用まで

Templateの基本確認今日は・C++未経験者・C++初心者・C++初心者(意味深)

・C++中級者及び上級者・歩くC++規格レベル・人間C++コンパイラなど色々な方が居る可能性があるので

Page 7: Template Meta Programming入門から応用まで

Templateの基本確認今日は・C++未経験者・C++初心者・C++初心者(意味深)

・C++中級者及び上級者・歩くC++規格レベル・人間C++コンパイラなど色々な方が居る可能性があるので

Page 8: Template Meta Programming入門から応用まで

Templateの基本確認今日は・C++未経験者・C++初心者・C++初心者(意味深)

・C++中級者及び上級者・歩くC++規格レベル・人間C++コンパイラなど色々な方が居る可能性があるので

Page 9: Template Meta Programming入門から応用まで

Templateの基本確認今日は・C++未経験者・C++初心者・C++初心者(意味深)

・C++中級者及び上級者・歩くC++規格レベル・人間C++コンパイラなど色々な方が居る可能性があるので

Page 10: Template Meta Programming入門から応用まで

Templateの基本確認今日は・C++未経験者・C++初心者・C++初心者(意味深)

・C++中級者及び上級者・歩くC++規格レベル・人間C++コンパイラなど色々な方が居る可能性があるので

Page 11: Template Meta Programming入門から応用まで

Templateの基本確認今日は・C++未経験者・C++初心者・C++初心者(意味深)

・C++中級者及び上級者・歩くC++規格レベル・人間C++コンパイラなど色々な方が居る可能性があるので

Page 12: Template Meta Programming入門から応用まで

Templateの基本確認今日は・C++未経験者・C++初心者・C++初心者(意味深)

・C++中級者及び上級者・歩くC++規格レベル・人間C++コンパイラなど色々な方が居る可能性があるので

Page 13: Template Meta Programming入門から応用まで

Templateの基本確認

ガチ勢の方はお手柔らかにお願いします

Page 14: Template Meta Programming入門から応用まで

Templateの基本確認

初心者は知らないことがあるかもそうでない人も少しおさらいをしておく

という意味で

Page 15: Template Meta Programming入門から応用まで

Templateの基本確認

規格に基づいて文法などのTemplateの基本を確認する

 

Page 16: Template Meta Programming入門から応用まで

Templateの基本確認

規格に基づいて文法などのTemplateの基本を確認する

むしろややこしいTemplateのルールについて把握する事こそがTemplate Meta Programming

最大の山場といえます

Page 17: Template Meta Programming入門から応用まで

Templateの基本確認

規格に基づいて文法などのTemplateの基本を確認する

非常に重要な部分であり、templateを使った経験が少ないとこれだけで十分すぎるぐらいつらいと思います

Page 18: Template Meta Programming入門から応用まで

Templateの基本確認

・C++11規格に沿う・ただし細かい部分には触れない (各自で規格を確認してほしい  自分もまる覚えはしていない)

・C++14~の機能(Variable Templates等)

 はその他付録の章で扱う

Page 19: Template Meta Programming入門から応用まで

Templateの基本確認

結構量があるので既に知ってる人は適当に聞き流しつつ他の作業でもしていて下さい

Page 20: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 21: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 22: Template Meta Programming入門から応用まで

Template is 何

テンプレートって何ですか?

Page 23: Template Meta Programming入門から応用まで

Template is 何

テンプレートって何ですか?N3337見ましょう

Page 24: Template Meta Programming入門から応用まで

Template is 何

14 Templates

A template defines a family of classes or functions or an alias for a family of types.

Page 25: Template Meta Programming入門から応用まで

Template is 何

テンプレートは

クラスや関数、型エイリアスのファミリーを定義する

Page 26: Template Meta Programming入門から応用まで

Template is 何

確認するまでもなかったかもしれません

次に文法を確認していくことにします

Page 27: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 28: Template Meta Programming入門から応用まで

テンプレートの文法

テンプレートの文法を確認する 

Page 29: Template Meta Programming入門から応用まで

テンプレートの文法

テンプレートの文法を確認する規格を参照して定義から見ていく

Page 30: Template Meta Programming入門から応用まで

テンプレートの文法

テンプレートの文法を確認する

template-declaration:template < template-parameter-list > declaration

template-parameter-list: template-parametertemplate-parameter-list , template-parameter

Page 31: Template Meta Programming入門から応用まで

テンプレートの文法

テンプレートの文法を確認する

template-declaration:template < template-parameter-list > declaration

template-parameter-list: template-parametertemplate-parameter-list , template-parameter

Page 32: Template Meta Programming入門から応用まで

テンプレートの文法

テンプレートは

template < template-parameter-list > declaration として定義される

Page 33: Template Meta Programming入門から応用まで

テンプレートの文法

テンプレートは

template < template-parameter-list > declaration として定義される

Page 34: Template Meta Programming入門から応用まで

テンプレートの文法

template-parameter-listは

template-parameter 又はtemplate-parameter-list , template-parameter 

として定義される

Page 35: Template Meta Programming入門から応用まで

テンプレートの文法

template-parameter-listは

template-parameter 又はtemplate-parameter-list , template-parameter 

として定義される

Page 36: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 37: Template Meta Programming入門から応用まで

Template parametersThe syntax for template-parameters is:

template-parameter: type-parameterparameter-declaration

type-parameter:class ...opt identifieropt

class identifieropt= type-idtypename ...opt identifieropttypename identifieropt= type-idtemplate < template-parameter-list > class ...opt identifieropt template < template-parameter-list > class identifieropt= id-expression

optの後の要素は省略可能

Page 38: Template Meta Programming入門から応用まで

Template parametersThe syntax for template-parameters is:

template-parameter: type-parameterparameter-declaration

type-parameter:class ...opt identifieropt

class identifieropt= type-idtypename ...opt identifieropttypename identifieropt= type-idtemplate < template-parameter-list > class ...opt identifieropt template < template-parameter-list > class identifieropt= id-expression

optの後の要素は省略可能

Page 39: Template Meta Programming入門から応用まで

Template parameters

template-parameterは

type-parameter又はparameter-declaration 

である

Page 40: Template Meta Programming入門から応用まで

Template parameters

template-parameterは

type-parameter又はparameter-declaration 

である

Page 41: Template Meta Programming入門から応用まで

まずtype-parameterの定義の一部のみ紹介する

type-parameter : class ...opt identifieropt

class identifieropt= type-idtypename ...opt identifieropttypename identifieropt= type-id

optが付いた要素は省略可能一見種類が多い

type-parameter

Page 42: Template Meta Programming入門から応用まで

まずtype-parameterの定義の一部のみ紹介する

type-parameter : class ...opt identifieropt

class identifieropt= type-idtypename ...opt identifieropttypename identifieropt= type-id

対応する色のもの同士は実質同じまた = type-idの部分はデフォルト引数の有無

type-parameter

Page 43: Template Meta Programming入門から応用まで

定義の数は一見多いが実際は結構単純

順番に定義の意味を見ていく

type-parameter

Page 44: Template Meta Programming入門から応用まで

この4つにおいてtype-parameterの頭の部分ではclassキーワードとtypenameキーワードは同じ意味(他の場所では当然意味が違うので注意する、C++には文脈によって同じキーワードに複数の意味を持たせる文化がある)(例えばtemplate template parameterの場合違う)

type-parameter

Page 45: Template Meta Programming入門から応用まで

最も単純なtype-parameterを使ったtemplate例

template<class> (又はtemplate<typename>)

type-parameterのclassとtypenameキーワードは今後の説明ではclassで統一する(スライドの都合上、短い方がありがたい)

type-parameter

Page 46: Template Meta Programming入門から応用まで

type-parameter : class ...opt identifieropt

identifierはtype-parameterの名前

例template<class Type>

type-parameter

Page 47: Template Meta Programming入門から応用まで

type-parameter : class ...opt identifieropt = type-id

type-idがデフォルト引数になる

例template<class Type = int>

何も渡されなければTypeはintになる

type-parameter

Page 48: Template Meta Programming入門から応用まで

関数のデフォルト引数同様に

最初のデフォルト引数を持つパラメータ以降の全パラメータにデフォルト引数が必要

例template<class T1 = int, class T2 = int> class A;

type-parameter

Page 49: Template Meta Programming入門から応用まで

デフォルト引数の設定は複数に分けて書いても統合される(N3337 305p)

template<class T1, class T2 = int> class A;template<class T1 = int, class T2> class A; は以下に等しい

template<class T1 = int, class T2 = int> class A;

type-parameter

Page 50: Template Meta Programming入門から応用まで

当然後ろの要素から順に設定する必要があるtemplate<class T1 = int, class T2> class A;template<class T1, class T2 = int> class A;

この順だと1行目でダメです

error: no default argument for ‘T2’

type-parameter

Page 51: Template Meta Programming入門から応用まで

例まとめtemplate<class> 無名template<class = int> デフォルト引数有りtemplate<class Type> 名前有りtemplate<class Type = int> デフォルト引数有りtemplate<class T1, class T2> 複数のパラメータ

type-parameter

Page 52: Template Meta Programming入門から応用まで

別の定義は後の章で見るのでひとまずtype-parameterをこれで終わります

type-parameter

Page 53: Template Meta Programming入門から応用まで

Template parameters

template-parameterは

type-parameter又はparameter-declaration 

である

Page 54: Template Meta Programming入門から応用まで

parameter-declaration

parameter-declaration:attribute-specifier-seqopt decl-specifier-seq declarator

attribute-specifier-seqopt decl-specifier-seq declarator = initializer-clause

attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt

attribute-specifier-seqopt decl-specifier-seq abstract-declaratoropt= initializer-clause

Page 55: Template Meta Programming入門から応用まで

parameter-declarationは

non-type template-parameter (非型テンプレートパラメータ)の場合に使う

parameter-declaration

Page 56: Template Meta Programming入門から応用まで

例を見た方が早いtemplate<char C>template<int N>

渡される引数がnon-typeなtemplate-parameter

int Nやchar Cがparameter-declarationにあたる

non-type template-parameter

Page 57: Template Meta Programming入門から応用まで

もっと具体的な例

template< 

class T, // Tはまだ何型か分からない std::size_t N // Nはstd::size_t型のパラメータ> struct array;

std::array<int, 10>の要素数10を受け取っているNがnon-type template-parameter

non-type template-parameter

Page 58: Template Meta Programming入門から応用まで

全ての型が

non-type template-parameterに

なれるわけではない

non-type template-parameter

Page 59: Template Meta Programming入門から応用まで

non-type template-parameterになれる条件(重要)

1. integral or enumeration type(実質整数型)

2. pointer to object or pointer to function3. lvalue reference to object or lvalue reference to function4. pointer to member 5. std::nullptr_t (実質ポインタ型) (又はこれらにcv修飾子が付いたもの)

のいずれかを満たす型であるとき

non-type template-parameter

Page 60: Template Meta Programming入門から応用まで

non-type template-parameterになれる条件は

要するに整数型かポインタ型か左辺値参照

non-type template-parameter

Page 61: Template Meta Programming入門から応用まで

例template<std::size_t N>std::size_tは整数型のtypedefなのでwell-formed

class myClass {};template<myClass Arg>先程の条件を満たさないクラス等はill-formed

non-type template-parameter

Page 62: Template Meta Programming入門から応用まで

例 N3337 p305

template<double d> class X; // Error浮動小数点型は条件に一致しないtemplate<double* pd> class Y; // OKpointer to objectなのでOK

template<double& rd> class Z; // OKlvalue referenceなのでOK

non-type template-parameter

Page 63: Template Meta Programming入門から応用まで

右辺値は値渡しで受け取る必要があるnon-type template-parameterになれないrvalue referenceは論外だし、const lvalue referenceでもダメ(どうせ渡せる型が小さいデータなのでコピーで然程問題ない)

例template<int N> class X;using type = X<0>; // OK

template<const int& N> class Y;using type = Y<0>// error: ‘0’ is not a valid template argument because it is not an lvalue

non-type template-parameter

Page 64: Template Meta Programming入門から応用まで

non-type template-parameterに渡せるものにも条件がある

non-type template-parameter

Page 65: Template Meta Programming入門から応用まで

non-type template-parameterに渡せるもの

・定数式・関数のアドレス・外部リンケージのあるオブジェクト・静的クラス・メンバのアドレス

non-type template-parameter

Page 66: Template Meta Programming入門から応用まで

non-type template-parameterに渡せるもの

定数式(分類に不安があるが…)

・非型テンプレート引数(先程のNなど)

・コンパイル時定数(constexpr)

 (後で説明する)

・sizeofやsizeof...など

non-type template-parameter

Page 67: Template Meta Programming入門から応用まで

non-type template-parameterに渡せるもの

関数のアドレス・説明不要、f()などのアドレス

non-type template-parameter

Page 68: Template Meta Programming入門から応用まで

non-type template-parameterに渡せるもの

外部リンケージのあるオブジェクト・extern修飾されたもの

non-type template-parameter

Page 69: Template Meta Programming入門から応用まで

non-type template-parameterに渡せるもの

静的クラス・メンバのアドレス・説明不要、そのままの意味

non-type template-parameter

Page 70: Template Meta Programming入門から応用まで

template-parameterに関しては、他にも細かい事が大量に規定されているので適宜規格を調べる必要がある

template-parameter

Page 71: Template Meta Programming入門から応用まで

template-parameterまとめ・テンプレートパラメータには型パラメータ と非型パラメータがある・非型パラメータになるものや渡せるものは 限られている

template-parameter

Page 72: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 73: Template Meta Programming入門から応用まで

Class templates

A class template defines the layout and operations for an unbounded set of related types.

Page 74: Template Meta Programming入門から応用まで

Class templates

クラステンプレートは、関連する型(要するに扱う要素の型が違うだけのクラス群)のレイアウトをまとめて定義する

Page 75: Template Meta Programming入門から応用まで

Class templates例 汎用的な配列クラス N3337 P315template<class T> class Array { 

T* v; // Tは引数として渡された型に置き換わるint sz; public: explicit Array(int); T& operator[](int); T& elem(int i) { return v[i]; } 

};  

Array<int>やArray<char>は渡した型を扱える

Page 76: Template Meta Programming入門から応用まで

Class templatesクラスメンバテンプレート

class Test {public:

template<class T>T f(T arg) { return arg; } // 関数テンプレートは後で取り上げる

};  

クラスメンバもテンプレートに出来るoperator等もテンプレート化可能

Page 77: Template Meta Programming入門から応用まで

Class templates非型テンプレートパラメータを使う例template<std::size_t N>struct integer { // structも当然テンプレート化可能

static constexpr std::size_t value = N;}; Nの型にconst等は付いていなくても非型テンプレートパラメータは(暗黙に)コンパイル時に値が決まる定数として扱える(constexpr修飾された値の初期化にも使える)

Page 78: Template Meta Programming入門から応用まで

Class templates非型テンプレートパラメータを使う例template<std::size_t N>struct integer {

static constexpr std::size_t value = ++N;}; 当然、非型テンプレートパラメータの型の書き換えはill-formedである(定数なのでうっかり試みても失敗する)

error: increment of read-only location ‘N’

Page 79: Template Meta Programming入門から応用まで

Class templates

違法な例を招く行為(当然してはいけない)template<class T, T v>struct data { static constexpr T* get_address() {

return const_cast<T*>(&static_cast<const T&>(v));}

}; 

このような行為は万死に値する

Page 80: Template Meta Programming入門から応用まで

Class templates

補足事項Template specializations テンプレートの特殊化

Page 81: Template Meta Programming入門から応用まで

Class templates

Template specializationsテンプレートの特殊化template<class T = int> struct A { static int x;};template<class U> void g(U) { }template<> struct A<double> {}; // specialize for T == doubletemplate<> struct A<> { }; // specialize for T == inttemplate<> void g(char) { } // specialize for U == char

テンプレートクラスやテンプレート関数のtype-parameterにある値が入った状態のものは特殊化されているといえる

Page 82: Template Meta Programming入門から応用まで

Class templates

class template partial specializationsクラステンプレートの部分特殊化

Page 83: Template Meta Programming入門から応用まで

Class templates

例template<class T1, class T2, int I> class A {}; // unspecialized

template<class T, int I> class A<T, T*, I> {};template<class T1, class T2, int I> class A<T1*, T2, I> {};template<class T> class A<int, T*, 5> {};template<class T1, class T2, int I> class A<T1, T2*, I> {};

Page 84: Template Meta Programming入門から応用まで

Class templates

template<class T1, class T2, int I> class A {}; // unspecialized

template<class T, int I> class A<T, T*, I> {};

このように抽象的なテンプレートパラメータの数を減らし部分的に具体的要素に置き換えた特殊化を作る事が出来る

Page 85: Template Meta Programming入門から応用まで

Class templates

template<class T1, class T2, int I> class A {}; // unspecialized

template<class T, int I> class A<T, T*, I> {};

部分特殊化されたテンプレートは、条件を満たす場合には特殊化されていないテンプレートより優先的にマッチする

Page 86: Template Meta Programming入門から応用まで

Class templates

template<class T1, class T2, int I> class A {}; // unspecialized

template<class T, int I> class A<T, T*, I> {}; // classA<int, int*, 0>などの場合だけこちらの定義が使われる

ある条件を満たす場合のみ実装を切り替える事が出来るこれはTemplate Meta Programmingにおいて非常に重要

Page 87: Template Meta Programming入門から応用まで

Class templates

また、部分特殊化によってはtemplate<int N>struct A;

template<>struct A<0>;のようにtemplateの中身が空<>になることもあるが特に文法上問題無い

Page 88: Template Meta Programming入門から応用まで

Class templates

勿論、型テンプレートパラメータだけでなく非型テンプレートパラメータも部分特殊化出来る(例は後の章で登場する)

Page 89: Template Meta Programming入門から応用まで

Class templates

テンプレートの特殊化及び部分特殊化が出来るケースにも条件がある

Page 90: Template Meta Programming入門から応用まで

Class templates

テンプレートの特殊化が出来るケース特殊化できるOK : 名前空間スコープNG : クラススコープ

つまりクラスのメンバは特殊化不可能

Page 91: Template Meta Programming入門から応用まで

Class templates

テンプレートの部分特殊化が出来るケース部分特殊化できる:

OK : クラステンプレートNG : 関数テンプレート

部分特殊化は非クラスメンバのクラステンプレート限定の機能といえる

Page 92: Template Meta Programming入門から応用まで

Class templates

Class templatesまとめ・クラステンプレートは、 関連する型のレ イアウトをまとめて定義する・名前空間スコープのクラステンプレートの み部分特殊化によって実装を切り替え可

Page 93: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 94: Template Meta Programming入門から応用まで

Function templates

A function template defines an unbounded set of related functions.

Page 95: Template Meta Programming入門から応用まで

Function templates

関数テンプレートは、関連する関数(要するに扱う要素の型が違うだけの関数群)をまとめて定義する

Page 96: Template Meta Programming入門から応用まで

Function templates

例template<class T>T twice(T arg) {

return arg * 2;}

twice(2); // 4twice(2.5); // 5.0

整数も浮動小数点も扱える

Page 97: Template Meta Programming入門から応用まで

Function templates

Template argument deductionテンプレート引数の型推論

Page 98: Template Meta Programming入門から応用まで

Function templates

先程の例twice(2); twice(2.5);

twice<int>(2)と書かなくとも適切にint版のtwiceが呼ばれ、twice<double>(2.5)と書かなくとも適切にdouble版のtwiceが呼ばれた

Page 99: Template Meta Programming入門から応用まで

Function templates

このような引数からテンプレートパラメータ型を推論する機能が

Template argument deduction

Page 100: Template Meta Programming入門から応用まで

Function templates

幾つかの例外を除き、渡した型がそのまま推論される

Page 101: Template Meta Programming入門から応用まで

Function templates

例外1

・配列型(T[N])はポインタ(T*)に変換される・関数型(R(Args...))は関数ポインタ (R(*(Args...))に変換される

Page 102: Template Meta Programming入門から応用まで

Function templates

例外2

・値渡しの場合のみトップレベルのcv修飾子 が無視される

Page 103: Template Meta Programming入門から応用まで

Function templates

例外2

template<class T>T test(T arg) { return arg; }

int a = 0;test(a); // Tはint型

const int b = 0;test(b); // Tはint型

Page 104: Template Meta Programming入門から応用まで

Function templates

例外2

このような挙動の理由は、値コピーを取る場合、結局元のオブジェクトの値が変更される可能性が無いためとされる

const int b = 0;test(b); // (testの中ではbのコピーが扱われるのでbの値自体が変えられることはない、じゃあコピーするときはconst無視してもいいんじゃね)…とコンパイラは思う

Page 105: Template Meta Programming入門から応用まで

Function templates

例外2

constと同様にvolatileも無視される

Page 106: Template Meta Programming入門から応用まで

Function templates

例外2

よって値を変更する可能性のある参照やポインタ渡しの場合はcv修飾子も保持される

template<class T>T test(T& arg) { return arg; }

const int b = 0;test(b); // Tはint& const型

Page 107: Template Meta Programming入門から応用まで

Function templates

例外2

ただし明示的に渡せば、渡した通りになる

const int b = 0;test<const int>(b); // Tはconst intになる

Page 108: Template Meta Programming入門から応用まで

Function templates

例外2

cv修飾子が無視される可能性があるのはトップレベルの型のみである

例えばvector<const int>などのconst int部分はトップレベルではないので無視されない

Page 109: Template Meta Programming入門から応用まで

Function templates

当然非型テンプレートも推論してくれるtemplate<class T, T N>constexpr T get(std::integral_constant<T, N>) {

return N;}std::cout << get(std::integral_constant<int, 0>()) << std::endl; // T = int, N = 0と推論され、0が出力される

Page 110: Template Meta Programming入門から応用まで

Function templates

std::integral_constant<T, N>

のようにテンプレートクラスのテンプレートパラメータとしてネストされた内部の型でもTやNとして推論出来る

Page 111: Template Meta Programming入門から応用まで

Function templates

Template argument deductionの規格を厳密に読んで全てのルールを把握していくだけで尋常じゃない大変さなので残りは省略します

Page 112: Template Meta Programming入門から応用まで

Function templates

Function template overloading関数テンプレートのオーバーロード

Page 113: Template Meta Programming入門から応用まで

Function templates

部分特殊化は出来ないが特殊化は出来るこれらはオーバーロードされる

template<class T> void output(T val);

template<> void output(const std::string& val);

Page 114: Template Meta Programming入門から応用まで

Function templates

オーバーロードの解決に関しては省略する

N333714.5.6.2 Partial ordering of function templates を参照して欲しい

ambiguousになる例など取り上げられている

Page 115: Template Meta Programming入門から応用まで

Function templates

Function templatesまとめ

・関数テンプレートは引数から型を推論し てくれる・特殊化、オーバーロードが可能である

Page 116: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 117: Template Meta Programming入門から応用まで

Alias templates

1. A template-declaration in which the declaration is an alias-declaration declares the identifier to be a alias template. An alias template is a name for a family of types. The name of the alias template is a template-name.

Page 118: Template Meta Programming入門から応用まで

Alias templates

2. When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template.

Page 119: Template Meta Programming入門から応用まで

Alias templates

もはや訳すのも面倒なので実例を見る

Page 120: Template Meta Programming入門から応用まで

Alias templates

template <class T>using add_pointer = typename std::add_pointer< T >::type;

add_pointer<T>はstd::add_pointer< T >::typeと同じ型になる

Page 121: Template Meta Programming入門から応用まで

Alias templates

別にtemplateである必要は無い

using type = int; 

typeはint型の別名として使える、簡単!

Page 122: Template Meta Programming入門から応用まで

Alias templates

typedef int integer;

using integer = int;

は同じ効果typedefの代わりとして使える(ただし使えるのはC++11以降)

Page 123: Template Meta Programming入門から応用まで

Alias templates

Template Meta Programmingではtypenameとか::typeを書かなくて済むようにする為に使ったりする

template<class T>using add_p = typename std::add_pointer<T>::type;

add_p<int>; // int*

Page 124: Template Meta Programming入門から応用まで

Alias templates余談typedefは指定子である指定子の順番に意味は無い

typedef int Integer1; (こっちが多分メジャー)

int typedef Integer2; (稀に見かける)

// どちらもOK

int Integer3 typedef;  // これはダメ

Page 125: Template Meta Programming入門から応用まで

Alias templates

typedef int Integer1; のようにどうしてtypedef A B;の形がメジャーなのか?

Page 126: Template Meta Programming入門から応用まで

Alias templates

次のような例を考えるint typedef type; はOKだがint* typedef type; はダメ

「*」は、指定子(specifier)ではなく、宣言子(declarator)のため

Page 127: Template Meta Programming入門から応用まで

Alias templates

結論多分、typedefを最初に書かない場合には宣言子が出てきた時に面倒臭いから

Page 128: Template Meta Programming入門から応用まで

Alias templates

後方互換性を気にしなくていいなら正直typedefよりusingを使うと良いと思います(個人的にはusingの方が好き)

Page 129: Template Meta Programming入門から応用まで

Alias templates

余談template structなどの状態のメタ関数では遅延されるタイミングで正格評価される場合がある?(エイリアステンプレートにしたところコンパイル時間が大幅に伸びた経験がある)

Page 130: Template Meta Programming入門から応用まで

Alias templates

Alias templatesまとめ・usingを使う事で型の別名として使える・typedefと違いテンプレート化出来る

Page 131: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 132: Template Meta Programming入門から応用まで

Variadic templates

1. A template parameter pack is a template parameter that accepts zero or more template arguments.

Page 133: Template Meta Programming入門から応用まで

Variadic templates

2. A function parameter pack is a function parameter that accepts zero or more function arguments.

Page 134: Template Meta Programming入門から応用まで

Variadic templates

つまり、

・可変長引数を取るクラス・可変長引数を取る関数

の為の可変長引数テンプレート

Page 135: Template Meta Programming入門から応用まで

Variadic templatesThe syntax for template-parameters is:

template-parameter: type-parameterparameter-declaration

type-parameter:class ...opt identifieropt

class identifieropt= type-idtypename ...opt identifieropttypename identifieropt= type-idtemplate < template-parameter-list > class ...opt identifieropt template < template-parameter-list > class identifieropt= id-expression

optの後の要素は省略可能

Page 136: Template Meta Programming入門から応用まで

Variadic templates

先程Template parametersで飛ばした...opt を使う

また、「...」を規格上ellipsisと呼ぶ先の定義通りデフォルト引数は取れない

Page 137: Template Meta Programming入門から応用まで

Variadic templates

template<class... Types> struct Tuple {}; 

class...の部分は可変長引数テンプレートその名前はTypes

Page 138: Template Meta Programming入門から応用まで

Variadic templates

template<class... Types> struct Tuple {};

可変長引数テンプレートは0個以上の引数を好きなだけ受け取れる

勿論、非型テンプレート引数版も可能template<int... Indices> struct Numbers {};

Page 139: Template Meta Programming入門から応用まで

Variadic templates

template<class... Types> struct Tuple {};

例Tuple<int, double, char, void*> このように好きなだけ渡せる

template<int... Indices> struct Numbers {};Numbers<1,2,3,4,5>

Page 140: Template Meta Programming入門から応用まで

Variadic templates

このような可変長引数部分の事をtemplate parameter pack と呼ぶ

Page 141: Template Meta Programming入門から応用まで

Variadic templates

例template<class... Types>struct List;

template<class Type, Type... Args>struct Data;

TypesやArgsはTemplate Parameter Pack

Page 142: Template Meta Programming入門から応用まで

Variadic templates

可変長引数テンプレートは基本的には、template parameterのうち最後でなければならない(一部例外がある)

template<class Type, class... Types> // OKtemplate<class... Types, class Type> // NG

Page 143: Template Meta Programming入門から応用まで

Variadic templates例外template<std::size_t... Indices1, std::size_t... Indices2>void f(index_tuple<Indices1...>, index_tuple<Indices2...>);

・関数の引数の型が持つパラメータパック を推論する場合・特に可変長引数を持つ型の引数を複数受 け取る場合には複数のパラメータパック を持つことが出来る

Page 144: Template Meta Programming入門から応用まで

Variadic templates

pack expansion 受け取ったパラメータパックを展開する

Page 145: Template Meta Programming入門から応用まで

Variadic templates

可変長引数として受け取ったテンプレートパラメータパックを使う為には

それを展開する必要がある

Page 146: Template Meta Programming入門から応用まで

Variadic templates

展開はpattern and an ellipsisからなる

Page 147: Template Meta Programming入門から応用まで

Variadic templates

template<class ResultType, class... Types>ResultType sum(const Types&... Args);

sum<int>(1,2,3,4,5,6,7,8,9,10);

可変長の関数テンプレートにおいて型推論を行い、その結果をTypesに格納して受け取っている

Page 148: Template Meta Programming入門から応用まで

Variadic templates

template<class Type, class... Types>Type sum(const Types&... Args);

におけるconst Types&...がパック展開

class... Typesはsum<int>(1,2,3,4,5,6,7,8,9,10);

なのでTypesはint, int, int, int, int, int, int, int, int, int

に推論される

Page 149: Template Meta Programming入門から応用まで

Variadic templates

このときTypes...はint, int, int, int, int, int, int, int, int, int に展開される

Page 150: Template Meta Programming入門から応用まで

Variadic templatespatternはパック展開時に処理を施すconst Types&...はTypesの受け取った型1つ1つにconst修飾及び参照&を付加した型になる

よってconst Types&...はconst int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int& に展開される

Page 151: Template Meta Programming入門から応用まで

Variadic templates結果としてtemplate<class ResultType, class... Types>ResultType sum(const Types&... Args);はsum<int>(1,2,3,4,5,6,7,8,9,10);のとき

int sum<int>(const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&, const int&);

と等価になっている

Page 152: Template Meta Programming入門から応用まで

Variadic templates

同様にして関数の引数もparameter packとして受け取っている

template<class ResultType, class... Types>ResultType sum(const Types&... Args);

Page 153: Template Meta Programming入門から応用まで

Variadic templates

sum<int>(1,2,3,4,5,6,7,8,9,10);のとき

Args...は1,2,3,4,5,6,7,8,9,10になる

Page 154: Template Meta Programming入門から応用まで

Variadic templates例として受け取った数の総和を計算する関数を挙げるtemplate<class Type, class... Types>Type sum(const Types&... Args) { // parameter pack Type result = 0; for(auto& elem : { static_cast<Type>(Args)... }) // pack expansion { result += elem; } return result;}

int main() { std::cout << sum<int>(1,2,3,4,5,6,7,8,9,10) << std::endl; // 55}

Page 155: Template Meta Programming入門から応用まで

Variadic templatesこの例ではinitializer-listに対して

{ static_cast<Type>(Args)... }

を展開することで

{static_cast<Type>(1), static_cast<Type>(2), static_cast<Type>(3), 

中略, static_cast<Type>(10)}

を生成している

結果として今回は全要素がint型の{1,2,3,4,5,6,7,8,9,10}になる

Page 156: Template Meta Programming入門から応用まで

Variadic templates

sum<int>(1,2.0,3.5,4,5,6,7,8,9,10);

のように型が異なる要素が混入していてもキャストしながら展開する事が出来る

Page 157: Template Meta Programming入門から応用まで

Variadic templates

補足template parameter packの要素数を得るにはsizeof...を使う

sizeof...(Types)sizeof...(Args)

sizeof...に対してはパックは展開せずに渡すsizeof...(Types...) // NG

Page 158: Template Meta Programming入門から応用まで

Variadic templates

余談ピリオドが6つ連続するコードが存在し得る(多分Sprout等で稀にお目にかかれる)

例template<class... T>void f(T......); // なにこれキモイ

Page 159: Template Meta Programming入門から応用まで

Variadic templates

これは前半3つのピリオドがVariadic Templatesの展開、後半3つのピリオドがC言語スタイルの可変長引数の...であり、真ん中のカンマが省略されたもの

template<class... T>void f(T..., ...); // ただのellipsis, ellipsisにすぎない

に等しいのでビビる必要は無い

Page 160: Template Meta Programming入門から応用まで

Variadic templates

Variadic templatesまとめ・Variadic TemplatesはTemplate Parameter Packと して受け取る・型パラメータ、非型パラメータを扱える・型パラメータは関数の引数の型として利用出来る・非型パラメータは関数の引数として利用出来る・Template Parameter Packはpattern and ellipsis

 によって展開してから使う

Page 161: Template Meta Programming入門から応用まで

Templateの基本確認目次1. Template is 何2. テンプレートの文法

2-1. テンプレートパラメータ 2-2. クラステンプレート 2-3. 関数テンプレート 2-4. エイリアステンプレート 2-5. 可変長引数テンプレート 2-6. template template parameter

Page 162: Template Meta Programming入門から応用まで

The syntax for template-parameters is:

template-parameter: type-parameterparameter-declaration

type-parameter:class ...opt identifieropt

class identifieropt= type-idtypename ...opt identifieropttypename identifieropt= type-idtemplate < template-parameter-list > class ...opt identifieropt template < template-parameter-list > class identifieropt= id-expression

optの後の要素は省略可能

Template Template Parameters

Page 163: Template Meta Programming入門から応用まで

Template Template Parameters

template <class Container>class hoge; ではhoge<std::vector<int>> h; は出来てもhoge<std::vector> h; は出来ない

Page 164: Template Meta Programming入門から応用まで

Template Template Parameters

要するにテンプレートクラス自体などを受け取る為のテンプレートパラメータ

Page 165: Template Meta Programming入門から応用まで

Template Template Parameters

アキラさんのブログに分かりやすい例があったので引用するtemplate <class T>class vector;

template <template<class> class Container>class hoge { Container<int> c;};

hoge<vector> h; // OK

Page 166: Template Meta Programming入門から応用まで

Template Template Parameters

template < template-parameter-list > class ...opt identifieropt template < template-parameter-list > class identifieropt= id-expression

このようにして受け取れるoptにellipsisがあるように可変長引数でも可能

Page 167: Template Meta Programming入門から応用まで

Template Template Parameters

Template Template Parametersまとめ・テンプレートクラス等を受け取る場合に 使う為のTemplate Parameter

Page 168: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 169: Template Meta Programming入門から応用まで

Template Meta Programmingとは

お疲れ様でした、テンプレートの機能をひと通り確認するだけで絶望的な量でした

これでも相当、本当に沢山端折って説明したので規格自体はこの数倍の量があります

Page 170: Template Meta Programming入門から応用まで

Template Meta Programmingとは

がっかりしたところで、初心者も最低限の知識が付いたと思うので二章に入ります

Page 171: Template Meta Programming入門から応用まで

Template Meta Programmingとは

Template Meta Programmingとは何か

Page 172: Template Meta Programming入門から応用まで

Template Meta Programmingとは

テンプレートを利用して、型や値に関する演算・処理をコンパイル時に行う技法

よく省略してTMPと呼ばれる

Page 173: Template Meta Programming入門から応用まで

Template Meta Programmingとは

テンプレートはコンパイル時に処理されるのでこの技法ではコンパイル時に計算が出来る

Page 174: Template Meta Programming入門から応用まで

Template Meta Programmingとは

この技法を用いた機能が標準ライブラリにもtype_traitsをはじめ多く含まれている

Page 175: Template Meta Programming入門から応用まで

Template Meta Programmingとは

大きく分けて

・型を処理するもの・値(として型)を処理するもの

に分けられる

Page 176: Template Meta Programming入門から応用まで

Template Meta Programmingとは

型を処理するものはたいてい

template<class T> 

のような型パラメータを使って型を操作していく

Page 177: Template Meta Programming入門から応用まで

Template Meta Programmingとは

値(として型)を処理するものはたいてい

template<int N> 

のような非型パラメータを使って値(として使えるような型)を操作していく

Page 178: Template Meta Programming入門から応用まで

Template Meta Programmingとは

次章で実例を見ていくとしましょう

Page 179: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 180: Template Meta Programming入門から応用まで

Template Meta Programming入門

この章では実例を見ていく初心者向けに最も単純な例から取り上げる

Page 181: Template Meta Programming入門から応用まで

Template Meta Programming入門

例1

型を受け取って値を返すもの

Page 182: Template Meta Programming入門から応用まで

Template Meta Programming入門

例えばある2つの型を比較して

同じ型であればtrue

異なる型であればfalse

を得たい

Page 183: Template Meta Programming入門から応用まで

Template Meta Programming入門

そのような機能を提供する

std::is_same

が標準ライブラリにはある

Page 184: Template Meta Programming入門から応用まで

Template Meta Programming入門

これは以下のように使う

std::is_same<int, int>::value // truestd::is_same<int, unsigned int>::value // false

Page 185: Template Meta Programming入門から応用まで

Template Meta Programming入門

実装はどうなっているのか

Page 186: Template Meta Programming入門から応用まで

Template Meta Programming入門

宣言template<class T, class U>struct is_same; ただ2つの型を受け取る

Page 187: Template Meta Programming入門から応用まで

Template Meta Programming入門

問題はどうやって判別して結果を変えるか

Page 188: Template Meta Programming入門から応用まで

Template Meta Programming入門

答え : 部分特殊化を使う

Page 189: Template Meta Programming入門から応用まで

Template Meta Programming入門

template<class T, class U> // different typesstruct is_same {

static constexpr auto value = false;};

template<class T> // same typestruct is_same<T, T> {

static constexpr auto value = true;};

Page 190: Template Meta Programming入門から応用まで

Template Meta Programming入門

template<class T>struct is_same<T, T> {

static constexpr auto value = true;};

両辺に同じ型が渡された場合のみこちらの定義が使われる

Page 191: Template Meta Programming入門から応用まで

Template Meta Programming入門

条件分岐 → 部分特殊化を使う

Page 192: Template Meta Programming入門から応用まで

Template Meta Programming入門

結果の返し方

静的なメンバ定数を定義するstatic constexpr auto value = true; // ただの静的定数でも良い

そうすれば、is_same<int, int>::valueのようにして得られる

Page 193: Template Meta Programming入門から応用まで

Template Meta Programming入門

このような実質関数として働くようなテンプレートクラスはmeta functionと呼ばれる

Page 194: Template Meta Programming入門から応用まで

Template Meta Programming入門

例2

値を受け取って型を返すもの

Page 195: Template Meta Programming入門から応用まで

Template Meta Programming入門

条件式によって違う型を返すメタ関数

Page 196: Template Meta Programming入門から応用まで

Template Meta Programming入門std::conditionalと同じ働きのメタ関数

template<bool B, class T, class F> // truestruct conditional { using type = T; }; template<class T, class F> // falsestruct conditional<false, T, F> { using type = F; };

型を返す場合はメンバ型を定義してやる

typename conditional<true, int, char>::type // int

Page 197: Template Meta Programming入門から応用まで

Template Meta Programming入門

例3

非型テンプレートパラメータによる演算

Page 198: Template Meta Programming入門から応用まで

Template Meta Programming入門

template<int X, int Y>struct add {

static constexpr auto value = X + Y;};

add<1, 2>::value // 3

非型パラメータを用いてコンパイル時に演算

Page 199: Template Meta Programming入門から応用まで

Template Meta Programming入門

発展例階乗の計算

Page 200: Template Meta Programming入門から応用まで

Template Meta Programming入門template<int i>struct fact{ static constexpr auto value = i * fact<i - 1>::value;}; template<>struct fact<1> // 1の場合{ static constexpr auto value = 1;};

階乗の計算ではvalueの定義にfact<i - 1>::valueを利用することで再帰を実現する

Page 201: Template Meta Programming入門から応用まで

Template Meta Programming入門

template<>struct fact<1> // 1の場合{ static constexpr auto value = 1;};

1の部分特殊化が無いと再帰が止まらなくなる事に注意する

Page 202: Template Meta Programming入門から応用まで

Template Meta Programming入門注意template<int i>struct fact{ static constexpr auto value = i > 1? i * fact<i - 1>::value : 1; // 再帰が止まらない};

三項演算子はtrueの場合も両辺の型の等価性を確認するために両辺ともインスタンス化しようとするので、再帰が止まらない(trueでもfact<i - 1>::valueをインスタンス化する)

Page 203: Template Meta Programming入門から応用まで

Template Meta Programming入門余談インスタンス化を遅らせて出来る限り型のまま処理することで部分特殊化無しで実装出来る場合もあるtemplate<std::size_t i>struct fact{ static constexpr auto value = i * std::conditional< (i > 1), fact<i - 1>, std::integral_constant<std::size_t, 1> >::type::value;}; これは再帰が止まるconditionalの両辺をメタ関数にして遅延評価させる

Page 204: Template Meta Programming入門から応用まで

Template Meta Programming入門まとめ1

メタ関数には単純な例だけでも入力として・値を受け取るもの・型を受け取るもの出力として・値を返すもの・型を返すものがある

Page 205: Template Meta Programming入門から応用まで

Template Meta Programming入門まとめ2

条件分岐・クラステンプレートの部分特殊化を使う(後でenable_if等も取り上げる)

結果の返し方・型を返すならばメンバ型を定義する・値を返すならば静的メンバ定数を定義する

名前は慣習として型であればtype、値であればvalueを使う

Page 206: Template Meta Programming入門から応用まで

Template Meta Programming入門

補足コンパイル時にエラーチェックさせる

Page 207: Template Meta Programming入門から応用まで

Template Meta Programming入門配列の要素数は正の値であるべきだtemplate<class T, std::size_t N, bool = (N > 0)> struct array; // 実装無し template<class T, std::size_t N>struct array<T, N, true> {// 実装}; array<int , 0> a; // 実装が無いのでコンパイルエラーになる

このような不正値に対して意図的にコンパイルエラーに出来るようなコードを書く技法は良く使われる

Page 208: Template Meta Programming入門から応用まで

Template Meta Programming入門

template<class T, std::size_t N, bool = (N > 0)>

比較演算子は括弧で囲む必要がある

std::vector<std::vector<int>>のようなネストされたテンプレートが>>演算子に解釈される問題はC++11以降では平気

Page 209: Template Meta Programming入門から応用まで

Template Meta Programming入門

補足static_assert

Page 210: Template Meta Programming入門から応用まで

Template Meta Programming入門コンパイル時アサートstatic_assert(fact<6>::value == 720, "");

コンパイル時に計算可能な値に対して用いるtrueであれば無出力falseであればコンパイルエラーになる

1番目の引数に条件式2番目の引数にエラー時のメッセージを渡す

当然、実行時計算されるような値を渡すと失敗扱い

Page 211: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 212: Template Meta Programming入門から応用まで

1. 関連知識をおさえる2. 実践(有用なイディオムと例)

Template Meta Programming応用

Page 213: Template Meta Programming入門から応用まで

Template Meta Programming応用

これからTMPの応用に入るその前に関連知識を知っておく

Page 214: Template Meta Programming入門から応用まで

Template Meta Programming応用

・constexpr

・decltype

・SFINAE

Page 215: Template Meta Programming入門から応用まで

補足constexpr

Template Meta Programming応用

Page 216: Template Meta Programming入門から応用まで

C++11のconstexprに関して軽く説明する私は陶芸家ではないので今回は深入りはしない

constexprに関して深く知りたい場合は・中3女子でもわかる!constexpr

・中3女子が教える本当に気持ちのいい constexpr

・constexpr中3女子テクニックなどの有益な情報の載ったスライドがWeb上に公開されているので各自Web上で検索して読むなどすると良い

Template Meta Programming応用

Page 217: Template Meta Programming入門から応用まで

TMPにおける値の計算は整数しか扱えないという弱点がある(浮動小数点を無理矢理エミュレートしようとする人は居るが…)

(また、一応ratioのようなものもあるが…)

またコンパイル時にしか使えないint a = 0;add<a, 1>::value; // エラー、aは実行時オブジェクト

Template Meta Programming応用

Page 218: Template Meta Programming入門から応用まで

C++03やconstexpr非対応のコンパイラの場合はTMPを使うが、そうでない場合はただ値を計算して、値を返すだけのようなメタ関数はconstexpr関数で実装した方が好ましい事も多いと思われる

Template Meta Programming応用

Page 219: Template Meta Programming入門から応用まで

// コンパイル時に計算可能template<class T>constexpr T add(T x, T y){

return x + y;}

見慣れた関数の形で実装出来る実行時にも共通のインタフェースで使える浮動小数点もOK

Template Meta Programming応用

Page 220: Template Meta Programming入門から応用まで

次のような式はconstant expressionsと呼ばれる。(Constant

expressionはコンパイル時に評価され得る)

constant-expression:conditional-expression

以降の条件部分はかなり細かいので、発表では適当に流すので各自確認しておいて欲しい

次ページ以降の条件に当てはまる場合、constexprにはなれない

Template Meta Programming応用

Page 221: Template Meta Programming入門から応用まで

条件

・this (非静的メンバ関数の本体に暗黙の変換の結果を含む、クラスメンバアクセス式の後置式、として表れていない場合)

・リテラルクラスのconstexprコンストラクタとconstexpr関数以外の関数呼び出し(オーバーロードの解決は普段通り適用される)

・constexpr関数やconstexprコンストラクタの定義の外での未定義動作のconstexpr関数や、未定義動作のconstexprコンストラクタの呼び出し

Template Meta Programming応用

Page 222: Template Meta Programming入門から応用まで

条件・constant expressionを生成しないような引数を用いてのconstexpr関数の呼び出し

例constexpr const int* addr(const int& ir) { return &ir; } // OK static const int x = 5;constexpr const int* xp = addr(x); // OK constant expressionなアドレスconstexpr const int* tp = addr(5); // エラー 一時アドレスの取得はconstant

expressionではない

Template Meta Programming応用

Page 223: Template Meta Programming入門から応用まで

条件・constant expressionを生成しないような引数による、初期化リストのみからなるconstexprコンストラクタの呼び出し

例int x; // not constantstruct A { constexpr A(bool b) : m(b?42:x) { } int m;};constexpr int v = A(true).m; // OKconstexpr int w = A(false).m; // エラー mの初期化に用いられるxが定数でない

Template Meta Programming応用

Page 224: Template Meta Programming入門から応用まで

条件・constexpr関数又はconstexprコンストラクタの再帰呼び出しが処理系の定義する制限を超える場合(Annex Bを参照)

Annex BにおいてRecursive constexpr function invocations [512].と定義されている・数学上定義されないような値、又は特定の型で扱える範囲外のその型の値。・ラムダ式・次の場合を除く左辺値から右辺値への変換 ・constant expressionで事前に初期化された非volatileなconstオブジェクトを参照する整数型のglvalue又はenum

 ・constexpr修飾で定義された、非volatileのオブジェクトかそのようなサブオブジェクトを参照するリテラル型のglvalue

 ・constant expressionで初期化された寿命の尽きていない一時オブジェクトを参照するリテラル型のglvalue

Template Meta Programming応用

Page 225: Template Meta Programming入門から応用まで

条件・非activeなunionのメンバやサブオブジェクトを参照するglvalueに適用される左辺値から右辺値への変換・constant expressionによって初期化されていない状態の値やデータメンバ参照を参照するid-expression

・dynamic cast

・reinterpret_cast

・擬似destructorの呼び出し・インクリメント及びデクリメント操作・多態クラス型に対するtypeid式・new式・delete式

Template Meta Programming応用

Page 226: Template Meta Programming入門から応用まで

条件・ポインタ同士の減算

・結果が不特定な場所での比較に関連するような演算子(rational or equality

operator)

・代入及び複合代入・throw式

Template Meta Programming応用

Page 227: Template Meta Programming入門から応用まで

更に補足実行時計算とコンパイル時計算の浮動小数点演算の精度は異なる場合がある

Template Meta Programming応用

Page 228: Template Meta Programming入門から応用まで

規格では浮動小数点の演算精度に関して制限を課さないので、コンパイル時と実行時における同じ式の浮動小数点演算の結果が同じである保証は無い(N3337 5.19 Constant expressions)

bool f() { char array[1 + int(1 + 0.2 - 0.1 - 0.1)]; // 必ずコンパイル時に計算される int size = 1 + int(1 + 0.2 - 0.1 - 0.1); // 実行時に計算されるかもしれない return sizeof(array) == size;}

f()の結果がtrueであるかfalseであるかは未定義である。

Template Meta Programming応用

Page 229: Template Meta Programming入門から応用まで

・整数演算しか出来ないTMPに比べ constexprは浮動小数点演算もコンパイル 時に出来る・コンパイル時計算にしか使えないTMPに比 べconstexprは実行時計算にも使える・逆に型に関する処理はTMPでしか実現出 来ない(TMPの独壇場)

Template Meta Programming応用

Page 230: Template Meta Programming入門から応用まで

補足decltype

Template Meta Programming応用

Page 231: Template Meta Programming入門から応用まで

decltypeイメージとしてはsizeofの型バージョン

Template Meta Programming応用

Page 232: Template Meta Programming入門から応用まで

decltypeThe type denoted by decltype(e) is defined as follows:— if e is an unparenthesized id-expression or an unparenthesized class member access (5.2.5), decltype(e) is the type of the entity named by e. If there is no such entity, or if e names a set of overloaded functions, the program is ill-formed;— otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;— otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;— otherwise, decltype(e) is the type of e.

Template Meta Programming応用

Page 233: Template Meta Programming入門から応用まで

decltype

if e is an unparenthesized id-expression or an unparenthesized class member access ...

要するにexpressionが括弧で囲まれていないような

decltype(expression)の形のものの場合

Template Meta Programming応用

Page 234: Template Meta Programming入門から応用まで

例char a;decltype(a); // char

int b = 1;int& c = b;decltype(c); // int&

const int* d;decltype(d); // const int*

Template Meta Programming応用

Page 235: Template Meta Programming入門から応用まで

例struct a_type { using type = int; };

a_type a;decltype(a); // a_typedecltype(a)::type; // int

void f(int);decltype(f); // void (int)

Template Meta Programming応用

Page 236: Template Meta Programming入門から応用まで

例void f(int);void f(double);decltype(f); // Error

関数に複数のオーバーロードがあるとダメ

Template Meta Programming応用

Page 237: Template Meta Programming入門から応用まで

例int f();decltype(f()); // int

関数の戻り値の型も取れる

decltype(e)のeのexpressionが評価されることはないので関数の定義は必要ない(TMPにおいて重要)

Template Meta Programming応用

Page 238: Template Meta Programming入門から応用まで

decltypedecltype((expression))の形のものの場合

Template Meta Programming応用

Page 239: Template Meta Programming入門から応用まで

decltype

otherwise, if e is an xvalue, decltype(e) is T&&, where T is the type of e;

decltype((expression))のような括弧で囲まれたもので、かつxvalueの場合T&&になる

xvalueはrvalue referenceを返す関数の呼び出しとそれに準ずるもののイメージ(std::moveなども含まれる)

Template Meta Programming応用

Page 240: Template Meta Programming入門から応用まで

decltype

otherwise, if e is an lvalue, decltype(e) is T&, where T is the type of e;

decltype((expression))のような括弧で囲まれたもので、かつlvalueの場合T&になる

Template Meta Programming応用

Page 241: Template Meta Programming入門から応用まで

decltype

otherwise, decltype(e) is the type of e.

それ以外(prvalue等)はeの型

例decltype(1); // intdecltype("hello,world"); // const char[12]

Template Meta Programming応用

Page 242: Template Meta Programming入門から応用まで

decltypeまとめ・decltypeを使うとオブジェクトや関数の戻 り値の型を得る事が出来る・decltypeの結果は括弧の有無で変わる

Template Meta Programming応用

Page 243: Template Meta Programming入門から応用まで

補足SFINAE

Template Meta Programming応用

Page 244: Template Meta Programming入門から応用まで

SFINAESubstitution failure is not an error

Template Meta Programming応用

Page 245: Template Meta Programming入門から応用まで

テンプレートの置き換えに失敗してもすぐにはエラーにならず他の候補を探す

必修知識だがC++入門書には多分載ってない(結果として知らない人も居る印象)

Template Meta Programming応用

Page 246: Template Meta Programming入門から応用まで

言葉より実例を見るほうが早い

Template Meta Programming応用

Page 247: Template Meta Programming入門から応用まで

struct Test { typedef int foo;}; template <typename T> void f(typename T::foo) {} // Definition #1  template <typename T> void f(T) {} // Definition #2  int main() { f<Test>(10);  f<int>(10); }

Template Meta Programming応用

Page 248: Template Meta Programming入門から応用まで

struct Test { typedef int foo;}; template <typename T> void f(typename T::foo) {} // Definition #1  template <typename T> void f(T) {} // Definition #2  int main() { f<Test>(10);  f<int>(10); }

Template Meta Programming応用

Page 249: Template Meta Programming入門から応用まで

struct Test { typedef int foo;}; template <typename T> void f(typename T::foo) {} // Definition #1  template <typename T> void f(T) {} // Definition #2  int main() { f<Test>(10);  f<int>(10); }

Template Meta Programming応用

Page 250: Template Meta Programming入門から応用まで

struct Test { typedef int foo;}; template <typename T> void f(typename T::foo) {} // Definition #1 定義にマッチする template <typename T> void f(T) {} // Definition #2  int main() { f<Test>(10); // Call #1.  f<int>(10); }

Template Meta Programming応用

Page 251: Template Meta Programming入門から応用まで

struct Test { typedef int foo;}; template <typename T> void f(typename T::foo) {} // Definition #1 int::fooは存在しない template <typename T> void f(T) {} // Definition #2  int main() { f<Test>(10); // Call #1.  f<int>(10); }

Template Meta Programming応用

Page 252: Template Meta Programming入門から応用まで

struct Test { typedef int foo;}; template <typename T> void f(typename T::foo) {} // Definition #1 呼出候補から外れる template <typename T> void f(T) {} // Definition #2  int main() { f<Test>(10); // Call #1.  f<int>(10); }

Template Meta Programming応用

Page 253: Template Meta Programming入門から応用まで

struct Test { typedef int foo;}; template <typename T> void f(typename T::foo) {} // Definition #1 エラーにはならない template <typename T> void f(T) {} // Definition #2 定義にマッチする int main() { f<Test>(10); // Call #1.  f<int>(10); // Call #2. }

Template Meta Programming応用

Page 254: Template Meta Programming入門から応用まで

このようなルールをSFINAEと呼ぶ条件分岐、エラーチェック等を実現出来る(例は後述)

Template Meta Programming応用

Page 255: Template Meta Programming入門から応用まで

1. 関連知識をおさえる2. 実践(有用なイディオムと例)

Template Meta Programming応用

Page 256: Template Meta Programming入門から応用まで

Template Meta Programming応用

関連知識をおさえたところでいよいよ応用として実用的なイディオム等を見ていく

Page 257: Template Meta Programming入門から応用まで

Template Meta Programming応用・Variadic templates  可変長引数テンプレートを扱う・enable_if  SFINAEによる条件分岐・index_tuple, index_range (index_sequence)  整数列パラメータパックの生成と利用・Expression Template(ET)

 式テンプレート

Page 258: Template Meta Programming入門から応用まで

Variadic templates 可変長引数テンプレートを扱う

Template Meta Programming応用

Page 259: Template Meta Programming入門から応用まで

要素の追加型リストを保持する単純なクラスtemplate<class... Types>struct list{

template<class Type>struct push_back{

using type = list<Types..., Type>; // これでOK

};};

Template Meta Programming応用

Page 260: Template Meta Programming入門から応用まで

要素の追加

例えばlist<int, char>::push_back<double>::typeのとき

Types...はint, charに展開され、Typeはdoubleであるから

list<Types..., Type>はlist<int, char, double>

Template Meta Programming応用

Page 261: Template Meta Programming入門から応用まで

要素の追加template<class... Types>struct list{

template<class Type>struct push_front{

using type = list<Type,Types...>; // これでOK

};};

push_frontも同様に可能

Template Meta Programming応用

Page 262: Template Meta Programming入門から応用まで

要素の削除template<class... Types>struct list{private:

template<class Type, class... Types2>struct pop_front_impl{

using type = list<Types2...>;};

public:struct pop_front { using type = typename pop_front_impl<Types...>::type; };

};

Template Meta Programming応用

Page 263: Template Meta Programming入門から応用まで

要素の削除

template<class Type, class... Types2>struct pop_front_impl{

using type = list<Types2...>;};

複数受け取ったパラメータのうちの最初の1つだけTypeに入り、残りは全てTypes2に入る

Template Meta Programming応用

Page 264: Template Meta Programming入門から応用まで

要素の削除pop_backだけは簡単にはいかない実装も他の操作に比べ面倒、計算コストもかかる

template<class... Types2, class Type> // エラー、可変長引数テンプレートはテンプレートパラメータのうち最後でなければならない

再帰的な実装など工夫が必要

Template Meta Programming応用

Page 265: Template Meta Programming入門から応用まで

enable_if SFINAEによる条件分岐

Template Meta Programming応用

Page 266: Template Meta Programming入門から応用まで

enable_if

・SFINAEを利用した条件分岐を手助けする イディオム・標準ライブラリにstd::enable_ifがある

Template Meta Programming応用

Page 267: Template Meta Programming入門から応用まで

enable_if

template<bool B, class T = void>struct enable_if {}; template<class T>struct enable_if<true, T> { typedef T type; };

つまり条件を満たした場合のみstd::enable_if<条件>::type

が定義される(SFINAEに利用出来る)

Template Meta Programming応用

Page 268: Template Meta Programming入門から応用まで

例template<class T>T foo2( T t, typename std::enable_if<std::is_integral<T>::value>::type* = 0) { return t;}

Tが整数型だった場合のみ呼び出し可能な関数Tが非整数型なら呼出候補から外される(もし呼出候補が1つも見つからなければコンパイルエラー)

不正な型の引数が渡される事を防止出来る

Template Meta Programming応用

Page 269: Template Meta Programming入門から応用まで

例template<class T, class Enable = void>class A; // undefined template<class T>class A<T, typename std::enable_if<std::is_floating_point<T>::value>::type> {};

条件を満たした場合のみ構築可能なクラスを部分特殊化で実現するSFINAEの対象は関数に限られたものではない

Template Meta Programming応用

Page 270: Template Meta Programming入門から応用まで

もっとenable_if enabler idiom

Template Meta Programming応用

Page 271: Template Meta Programming入門から応用まで

従来のenable_ifではオーバーロード出来ないtemplate<typename T, typename Enable = typename std::enable_if<std::is_integral<T>::value>::type>void f(T);

template<typename T, typename Enable = typename std::enable_if<std::is_pointer<T>::value>::type>void f(T); // デフォルト引数が異なるだけの再定義はダメ

Template Meta Programming応用

Page 272: Template Meta Programming入門から応用まで

type-parameterでのオーバーロードは厳しい

Template Meta Programming応用

Page 273: Template Meta Programming入門から応用まで

そこで以下のような宣言を行う

extern void * enabler;

Template Meta Programming応用

Page 274: Template Meta Programming入門から応用まで

extern void * enabler;

の定義は必要ない

enablerはextern修飾されているので外部リンケージを持つ

ということは

Template Meta Programming応用

Page 275: Template Meta Programming入門から応用まで

non-type template-parameterに渡せるもの

外部リンケージのあるオブジェクト・extern修飾されたもの

non-type template-parameter

Page 276: Template Meta Programming入門から応用まで

これはオーバーロード出来るtemplate<typename T, typename std::enable_if< std::is_integral<T>::value>::type *& = enabler>void f(T);

template<typename T, typename std::enable_if< std::is_pointer<T>::value>::type *& = enabler>void f(T);

Template Meta Programming応用

Page 277: Template Meta Programming入門から応用まで

template<typename T, typename std::enable_if< std::is_integral<T>::value>::type *& = enabler>void f(T);

enable_ifを非型パラメータとして用いているのがポイント(参照型は非型パラメータになれる)

enablerは外部リンケージを持つので非型パラメータに渡す事が出来る

Template Meta Programming応用

Page 278: Template Meta Programming入門から応用まで

わざわざ使わなくても十分なケースが多いしかし、必要になることもある

Template Meta Programming応用

Page 279: Template Meta Programming入門から応用まで

index_tuple, index_range (integer_sequence) 整数列パラメータパックの生成と利用

Template Meta Programming応用

Page 280: Template Meta Programming入門から応用まで

index_tuple idiomなどと呼ばれる・整数列のパラメータパックを生成するイ ディオム・C++14からはstd::integer_sequenceとして 同様の機能が標準ライブラリ入り・インデックスアクセス可能なデータ構造 の効率の良い要素の走査、リスト内包表 記相当の処理の実現

Template Meta Programming応用

Page 281: Template Meta Programming入門から応用まで

・整数列パラメータを保持する型・整数列パラメータを生成するヘルパメタ 関数のセットで用いられる

Template Meta Programming応用

Page 282: Template Meta Programming入門から応用まで

例えばNを正の整数としたとき

index_range<0, N>::typeがindex_tuple<0,1,2,3, ..., N-1> 

と同じ型になるように実装する

Template Meta Programming応用

Page 283: Template Meta Programming入門から応用まで

実装例(簡単でクソなO(N)オーダーでの実装)template<std::size_t... Indices>

struct index_tuple {};

template<std::size_t step, std::size_t last, class result = index_tuple<>, bool flag = step

>= last>

struct index_range

{

using type = result;

};

template<std::size_t step, std::size_t last, std::size_t... Indices>

struct index_range<step, last, index_tuple<Indices...>, false>

: index_range<step + 1, last, index_tuple<Indices..., step>>

{};

Template Meta Programming応用

Page 284: Template Meta Programming入門から応用まで

実装例(簡単でクソなO(N)オーダーでの実装)template<std::size_t... Indices>

struct index_tuple {};

template<std::size_t step, std::size_t last, class result = index_tuple<>, bool flag = step

>= last>

struct index_range

{

using type = result;

};

template<std::size_t step, std::size_t last, std::size_t... Indices>

struct index_range<step, last, index_tuple<Indices...>, false>

: index_range<step + 1, last, index_tuple<Indices..., step>>

{};

Template Meta Programming応用

Page 285: Template Meta Programming入門から応用まで

template<std::size_t... Indices>struct index_tuple {};

整数列パラメータを保持する型

例index_tuple<0,1,2,3,4,5> // 0,1,2,3,4,5を保持

Template Meta Programming応用

Page 286: Template Meta Programming入門から応用まで

index_rangeは整数列パラメータを生成するヘルパメタ関数

・結果を返す定義(デフォルト定義)

・整数列パラメータを生成するフローの為 の部分特殊化

の2つの定義がある

Template Meta Programming応用

Page 287: Template Meta Programming入門から応用まで

実装例(簡単でクソなO(N)オーダーでの実装)template<std::size_t... Indices>

struct index_tuple {};

template<std::size_t step, std::size_t last, class result = index_tuple<>, bool flag = step

>= last>

struct index_range

{

using type = result;

};

template<std::size_t step, std::size_t last, std::size_t... Indices>

struct index_range<step, last, index_tuple<Indices...>, false>

: index_range<step + 1, last, index_tuple<Indices..., step>>

{};

Template Meta Programming応用

Page 288: Template Meta Programming入門から応用まで

結果を返すデフォルト定義template<std::size_t step,std::size_t last, class result = index_tuple<>,bool flag = first >= last>struct index_range{ using type = result;};

Template Meta Programming応用

Page 289: Template Meta Programming入門から応用まで

パラメータの解説template< std::size_t step, // 現在処理している数(呼出は初期値を渡す)

std::size_t last, // 範囲の終わり(さきほどのN)

class result = index_tuple<>, // 結果型(デフォでindex_tuple<>)

bool flag = first >= last // 再帰の終了条件>struct index_range{ using type = result; // 型を定義して結果を返す};

Template Meta Programming応用

Page 290: Template Meta Programming入門から応用まで

実装例(簡単でクソなO(N)オーダーでの実装)template<std::size_t... Indices>

struct index_tuple {};

template<std::size_t step, std::size_t last, class result = index_tuple<>, bool flag = step

>= last>

struct index_range

{

using type = result;

};

template<std::size_t step, std::size_t last, std::size_t... Indices>

struct index_range<step, last, index_tuple<Indices...>, false>

: index_range<step + 1, last, index_tuple<Indices..., step>>

{};

Template Meta Programming応用

Page 291: Template Meta Programming入門から応用まで

生成フローの定義template<std::size_t step, // 現在処理している数std::size_t last, // 範囲の終わりstd::size_t... Indices // 結果の整数列パラメータ>struct index_range<step,last,index_tuple<Indices...>,false> : index_range<step + 1, last, index_tuple<Indices..., step>>{};

Template Meta Programming応用

Page 292: Template Meta Programming入門から応用まで

生成フローの定義template<std::size_t step, // 現在処理している数std::size_t last, // 範囲の終わりstd::size_t... Indices // 結果の整数列パラメータ>struct index_range<step,last,index_tuple<Indices...>,false> // falseで特殊化: index_range<step + 1, last, index_tuple<Indices..., step>>{};

Template Meta Programming応用

Page 293: Template Meta Programming入門から応用まで

デフォルト定義における以下の部分bool flag = first >= last // 再帰の終了条件がfalseになったときだけ部分特殊化された定義が使われる

すなわち生成フローの定義が使われる

Template Meta Programming応用

Page 294: Template Meta Programming入門から応用まで

生成フローの定義template<std::size_t step, // 現在処理している数std::size_t last, // 範囲の終わりstd::size_t... Indices // 結果の整数列パラメータ>struct index_range<step,last,index_tuple<Indices...>, false> // falseで特殊化: index_range<step + 1, last, index_tuple<Indices..., step>>{};

Template Meta Programming応用

Page 295: Template Meta Programming入門から応用まで

生成フローの定義template<std::size_t step, // 現在処理している数std::size_t last, // 範囲の終わりstd::size_t... Indices // 結果の整数列パラメータ>struct index_range<step,last,index_tuple<Indices...>, // 結果型はindex_tupleにIndicesを渡すfalse> // falseで特殊化: index_range<step + 1, last, index_tuple<Indices..., step>>{};

Template Meta Programming応用

Page 296: Template Meta Programming入門から応用まで

template<

std::size_t step, // 現在処理している数std::size_t last, // 範囲の終わりstd::size_t... Indices // 結果の整数列パラメータ>

struct index_range<

step,

last,

index_tuple<Indices...>, // 結果型はindex_tupleにIndices渡すfalse> // falseで特殊化

: index_range<step + 1, last, index_tuple<Indices..., step>>// パラメータ違いのindex_rangeを継承している{};

Template Meta Programming応用

Page 297: Template Meta Programming入門から応用まで

テンプレートパラメータ違いの自分自身を継承すること

: index_range<step + 1, last, index_tuple<Indices..., step>> 

メタ関数における再帰を意味する

テンプレートパラメータは関数の引数相当

Template Meta Programming応用

Page 298: Template Meta Programming入門から応用まで

: index_range<step + 1, last, index_tuple<Indices..., step>> 

この部分ではstepを1進め可変長引数テンプレートパラメータの要素にstepを追加して再帰する

index_tupleに渡す引数を増やしながら再帰している

Template Meta Programming応用

Page 299: Template Meta Programming入門から応用まで

結果を返すデフォルト定義に戻るtemplate<std::size_t step,std::size_t last, class result = index_tuple<>, // (index_tuple<Indices..., step>)bool flag = first >= last// stepがlastに達した時点で再帰が止まる>struct index_range{ using type = result; // 結果型};

Template Meta Programming応用

Page 300: Template Meta Programming入門から応用まで

実用例

Template Meta Programming応用

Page 301: Template Meta Programming入門から応用まで

配列クラスと値nを受けとり、全要素にnを加えた値の要素を持つ配列クラスを返す関数iota

template<class T, std::size_t N, std::size_t... Indices>constexpr auto iota_impl(const array<T, N> arr, const T n, index_tuple<Indices...>)-> array<T, N> { return array<T, N>{{(arr[Indices] + n)...}};}

template<class T, std::size_t N>constexpr auto iota(const array<T, N> arr, const T n) -> array<T, N> { return iota_impl(arr, n, typename index_range<0, N>::type());}

constexpr array<int, 9> arr1{{1,2,3,4,5,6,7,8,9}}; // 配列クラスのオブジェクト

constexpr auto arr2 = iota(arr1, 1); // iotaには配列クラスのオブジェクトと値nを渡してやる//結果としてarray<int, 9>{{2,3,4,5,6,7,8,9,10}}が欲しい

Template Meta Programming応用

Page 302: Template Meta Programming入門から応用まで

template<class T, std::size_t N, std::size_t... Indices>constexpr auto iota_impl(const array<T, N> arr, const T n, index_tuple<Indices...>)-> array<T, N> { return array<T, N>{{(arr[Indices] + n)...}};}

template<class T, std::size_t N>constexpr auto iota(const array<T, N> arr, const T n) -> array<T, N> { return iota_impl(arr, n, typename index_range<0, N>::type());}

constexpr array<int, 9> arr1{{1,2,3,4,5,6,7,8,9}};constexpr auto arr2 = iota(arr1, 1); // array<int, 9>{{2,3,4,5,6,7,8,9,10}}

Tはintに、Nは9に推論される

Template Meta Programming応用

Page 303: Template Meta Programming入門から応用まで

template<class T, std::size_t N, std::size_t... Indices>constexpr auto iota_impl(const array<T, N> arr, const T n, index_tuple<Indices...>)-> array<T, N> { return array<T, N>{{(arr[Indices] + n)...}};}

template<class T, std::size_t N>constexpr auto iota(const array<T, N> arr, const T n) -> array<T, N> { return iota_impl(arr, n, typename index_range<0, N>::type());}

constexpr array<int, 9> arr1{{1,2,3,4,5,6,7,8,9}};constexpr auto arr2 = iota(arr1, 1); // array<int, 9>{{2,3,4,5,6,7,8,9,10}}

この場合N = 9であるからindex_range<0, 9>::typeになる

Template Meta Programming応用

Page 304: Template Meta Programming入門から応用まで

template<class T, std::size_t N, std::size_t... Indices>constexpr auto iota_impl(const array<T, N> arr, const T n, index_tuple<Indices...>)-> array<T, N> { return array<T, N>{{(arr[Indices] + n)...}};}

template<class T, std::size_t N>constexpr auto iota(const array<T, N> arr, const T n) -> array<T, N> { return iota_impl(arr, n, typename index_range<0, N>::type());}

constexpr array<int, 9> arr1{{1,2,3,4,5,6,7,8,9}};constexpr auto arr2 = iota(arr1, 1); // array<int, 9>{{2,3,4,5,6,7,8,9,10}}

index_range<0, 9>::typeはindex_tuple<0,1,2,3,4,5,6,7,8>である

Template Meta Programming応用

Page 305: Template Meta Programming入門から応用まで

template<class T, std::size_t N, std::size_t... Indices>constexpr auto iota_impl(const array<T, N> arr, const T n, index_tuple<Indices...>)-> array<T, N> { return array<T, N>{{(arr[Indices] + n)...}};}

template<class T, std::size_t N>constexpr auto iota(const array<T, N> arr, const T n) -> array<T, N> { return iota_impl(arr, n, typename index_range<0, N>::type());}

constexpr array<int, 9> arr1{{1,2,3,4,5,6,7,8,9}};constexpr auto arr2 = iota(arr1, 1); // array<int, 9>{{2,3,4,5,6,7,8,9,10}}

結果としてindex_tuple<0,1,2,3,4,5,6,7,8>()がiota_implの引数として渡される

Template Meta Programming応用

Page 306: Template Meta Programming入門から応用まで

template<class T, std::size_t N, std::size_t... Indices> // Indices is 0,1,2,3,4,5,6,7,8constexpr auto iota_impl(const array<T, N> arr, const T n, index_tuple<Indices...>)-> array<T, N> { return array<T, N>{{(arr[Indices] + n)...}};}

template<class T, std::size_t N>constexpr auto iota(const array<T, N> arr, const T n) -> array<T, N> { return iota_impl(arr, n, typename index_range<0, N>::type());}

constexpr array<int, 9> arr1{{1,2,3,4,5,6,7,8,9}};constexpr auto arr2 = iota(arr1, 1); // array<int, 9>{{2,3,4,5,6,7,8,9,10}}

このときIndicesは0,1,2,3,4,5,6,7,8に推論される

Template Meta Programming応用

Page 307: Template Meta Programming入門から応用まで

template<class T, std::size_t N, std::size_t... Indices> // Indices is 0,1,2,3,4,5,6,7,8constexpr auto iota_impl(const array<T, N> arr, const T n, index_tuple<Indices...>)-> array<T, N> { return array<T, N>{{(arr[Indices] + n)...}};}

template<class T, std::size_t N>constexpr auto iota(const array<T, N> arr, const T n) -> array<T, N> { return iota_impl(arr, n, typename index_range<0, N>::type());}

constexpr array<int, 9> arr1{{1,2,3,4,5,6,7,8,9}};constexpr auto arr2 = iota(arr1, 1); // array<int, 9>{{2,3,4,5,6,7,8,9,10}}

最終的にarray<T, N>{{(arr[Indices] + n)...}}の部分はarray<int, 9>{{arr[0] + n, arr[1] + n, (中略)..., arr[8] + n}}

という風に展開される

Template Meta Programming応用

Page 308: Template Meta Programming入門から応用まで

基本的にインデックスアクセス可能なデータ構造であれば適用出来る

Template Meta Programming応用

Page 309: Template Meta Programming入門から応用まで

余談生成結果のメモ化

Template Meta Programming応用

Page 310: Template Meta Programming入門から応用まで

template<std::size_t First, std::size_t Last>struct index_tuple_memo{ static constexpr auto value = typename index_range<First, Last>::type();};

index_tuple系の生成結果のメモ化を行う試みtypename index_range::type()の呼び出し時にindex_tuple_memo::valueを代わりに使う事で使いまわす2回目以降の呼び出しでO(1)が期待出来る

Template Meta Programming応用

Page 311: Template Meta Programming入門から応用まで

・メモリ使用量が増える可能性・コンパイラの最適化によっては無意味 ・逆効果かも

同じ要素数で尚且つ数千要素のtuple展開を何度も行うような場合には有効かもしれないが通常は使わなくて良さそう

Template Meta Programming応用

Page 312: Template Meta Programming入門から応用まで

index_rangeの実装には簡単でクソなO(N)オーダーでの実装の他に有用なO(log2(N))オーダーでの実装法も知られている

Template Meta Programming応用

Page 313: Template Meta Programming入門から応用まで

線形オーダーでは扱える要素数が限られ、生成速度も遅い

のでSproutや標準ライブラリで後者の実装が使われている

Template Meta Programming応用

Page 314: Template Meta Programming入門から応用まで

アイデア概要

例えばN = 14のときIndicesが0,1,2,3,4,5,6であればindex_tuple<Indices..., (Indices + N/2)...> を展開すればindex_tuple<0,1,2,3,4,5,6,7,8,9,10,11,12,13> が得られる

現実には実装はもっと面倒だが基本的には、このように前の結果を利用して要素数を倍々にしていくという考え

Template Meta Programming応用

Page 315: Template Meta Programming入門から応用まで

詳しい実装に関してはsprout::index_rangeなどを見て欲しい

Template Meta Programming応用

Page 316: Template Meta Programming入門から応用まで

Expression Template(ET)式テンプレート

Template Meta Programming応用

Page 317: Template Meta Programming入門から応用まで

・式の評価を遅延させる・余計な一時オブジェクトの生成とコピーの 発生を防ぐ

Template Meta Programming応用

Page 318: Template Meta Programming入門から応用まで

通常、巨大な行列の一時オブジェクトが生成される演算に対して、演算の結果ではなく演算を表す型オブジェクトを返す

Template Meta Programming応用

Page 319: Template Meta Programming入門から応用まで

行列のA, B, Cの和A + B + C

ETを使わない実装では、A + Bで値を計算して一時オブジェクトを生成、更に一時オブジェクト + Cで値を計算して一時オブジェクトを生成という事が起こりうるその過程で巨大なオブジェクトのコピー、構築が起こりうる

Template Meta Programming応用

Page 320: Template Meta Programming入門から応用まで

行列のA, B, Cの和Plus<Plus<Vector<A>, Vector<B>>, Vector<C>>

演算を型として表す、巨大な行列をコピーしたりしなくて済むので、途中式の段階で一時オブジェクトの生成コストが非常に小さくなる

Template Meta Programming応用

Page 321: Template Meta Programming入門から応用まで

値はoperator=()が呼ばれた時に初めて評価される

Template Meta Programming応用

Page 322: Template Meta Programming入門から応用まで

参考ETの簡単な実装法やデメリット等も含めて紹介されている

日本で一番分かりやすく書いたつもりのExpression Templateの説明http://d.hatena.ne.jp/Cryolite/20040506

などが分かりやすい

Template Meta Programming応用

Page 323: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 324: Template Meta Programming入門から応用まで

その他付録

1. TMPとは直接関係ないイディオムなど2. これからのTMPと関連イディオムなど

Page 325: Template Meta Programming入門から応用まで

その他付録

型を受け取るユーザ定義リテラル

Page 326: Template Meta Programming入門から応用まで

その他付録

整数リテラルと浮動小数点リテラルに限りchar...のテンプレート実引数として受け取ることが出来る

Page 327: Template Meta Programming入門から応用まで

その他付録

template<char...>void operator "" _to_string() {};

12345_to_string; // template<‘1’,’2’,’3’,’4’,’5’>として渡される

3.14_to_string; // template<‘3’,’.’,’1’,,4>

Page 328: Template Meta Programming入門から応用まで

その他付録#include <sprout/index_tuple.hpp>

template<char last>constexpr auto indices()-> typename sprout::index_range<0, last - '0'>::type { return sprout::index_range<0, last - '0'>::make();}

template<char... last>constexpr auto operator "" _indices() -> decltype(indices<last...>()) { static_assert(sizeof...(last) == 1, ""); return indices<last...>();}

int main() { static_assert(std::is_same<decltype(2_indices), sprout::index_tuple<0,1>>::value, "");}

ユーザ定義リテラルを使ったindex_tupleの生成みたいなサンプル(実際にはchar同士の減算等にはもう少し気を配った方がいい感じがしますが)

Page 329: Template Meta Programming入門から応用まで

その他付録

型文字列の生成に使えるただし整数と浮動小数点のみ

ショージキ微妙だが今後に期待

Page 330: Template Meta Programming入門から応用まで

その他付録

private namespace idiom detail等へのアクセスを制限する

Page 331: Template Meta Programming入門から応用まで

その他付録namespace tmp {  namespace { // 無名名前空間 namespace detail { // detailへはアクセスされたくない void f_impl() {} // privateな実装 }  void f() { detail::f_impl(); } // publicなインタフェース }  namespace detail {}; // detailのメンバへのアクセスを殺す} tmp::f(); // OK tmp::detail::f_impl(); // ルックアップに失敗しエラー

Page 332: Template Meta Programming入門から応用まで

その他付録

無名名前空間が暗黙にusingされる事を逆手に取る

detailへのアクセスを殺せるので名前空間スコープで、メタ関数の内部実装にどうしてもアクセスされたくない場合には有効

Page 333: Template Meta Programming入門から応用まで

その他付録

1. TMPとは直接関係ないイディオムなど2. これからのTMPと関連イディオムなど

Page 334: Template Meta Programming入門から応用まで

その他付録

先程取り上げたinteger_sequenceの他にもある、C++14(所謂N3690辺り) / C++1y以降に入ると思われる機能とそれに関連する話(大雑把に未来の話です)

ただしTMPに割と関連しそうなものだけ

Page 335: Template Meta Programming入門から応用まで

その他付録

C++14以降で(ほぼ確実に)入る機能

Page 336: Template Meta Programming入門から応用まで

その他付録

constexprの制限緩和

Page 337: Template Meta Programming入門から応用まで

その他付録

・副作用、制御構文が使えるようになる・ポインタ同士の減算が定数式になるなど

一部制限が増えている・a conversion from type cv void * to a pointer-to-object type;

C++11ではreinterpret_castが禁止されていたのにvoid*の型変換が禁止されていなかったが、これもダメに修正された

Page 338: Template Meta Programming入門から応用まで

その他付録

ただし、constexpr関数では相変わらずエラーハンドリングが困難なので迂闊に副作用の濫用を行うと、例外安全性を保つのが難しいので注意が必要

その他、細かい事は規格等を参照して欲しい

Page 339: Template Meta Programming入門から応用まで

その他付録

decltype(auto)

Page 340: Template Meta Programming入門から応用まで

その他付録

decltype(auto)は、式をdecltype()の中に書いたのと同じ挙動になる

Page 341: Template Meta Programming入門から応用まで

その他付録

江添さんの記事が分かりやすいhttp://cpplover.blogspot.jp/2013/08/decltypeauto.html

Page 342: Template Meta Programming入門から応用まで

その他付録記事の例のみ引用する

int i = 0 ;int && f() ;

auto a1 = i ; // intdecltype(auto) a2 = i ; // int

auto b1 = (i) ; // intdecltype(auto) b2 = (i) ; // int &

auto c1 = f() ; // intdecltype(auto) c2 = f() ; // int &&

Page 343: Template Meta Programming入門から応用まで

その他付録

関数の戻り値などに利用出来る

template < typename T, typename U >auto g( T const & t, U const & u )-> decltype( auto ) // decltype( f( t, u ) )と書かなくて済む{ return f( t, u ) ;}

Page 344: Template Meta Programming入門から応用まで

その他付録

ジェネリックラムダ

Page 345: Template Meta Programming入門から応用まで

その他付録

ラムダ式もテンプレート化出来るauto NumElements = []<int N>(auto (&a)[N]) { return N; };

Page 346: Template Meta Programming入門から応用まで

その他付録

Variable Templates 変数テンプレート

Page 347: Template Meta Programming入門から応用まで

その他付録

読んで字の如く、変数をテンプレート化する

Page 348: Template Meta Programming入門から応用まで

その他付録

変数テンプレートtemplate<class T>constexpr T pi = static_cast<T>(3.14);

pi<int> == 3;pi<float> == 3.14;

異なる精度の値を得る

Page 349: Template Meta Programming入門から応用まで

その他付録

変数テンプレートtemplate<class T1, T2>constexpr bool is_same_v = std::is_same<T1, T2>::value;

is_same_v<int, double>; // false

面倒な::valueを書かずに済む

Page 350: Template Meta Programming入門から応用まで

その他付録

C++1y(ここではC++14よりも後を意味する)

以降で入るかもしれない提案

Page 351: Template Meta Programming入門から応用まで

その他付録

Concepts Lite 軽量コンセプト

Page 352: Template Meta Programming入門から応用まで

その他付録

C++11入りする予定だったConceptの軽量・改良版

幾つかペーパーのようなものが出ている模様

Page 353: Template Meta Programming入門から応用まで

その他付録

プログラマにやさしい構文で型制約を行えるようになる

constexpr関数として型制約を定義する案など

使えるようになるのは当分先の話になりそうな気はします

Page 354: Template Meta Programming入門から応用まで

その他付録

N3741Opaque Alias

Page 355: Template Meta Programming入門から応用まで

その他付録

Strong typedef ある型から別の型を作る

using identifier = access-specifier type-id opaque-definition

Page 356: Template Meta Programming入門から応用まで

その他付録

using age = private int; // intとは別の型として認識される// privateにより暗黙のキャストは許可しない

age age1 = static_cast<age>(20); // 明示的なキャストをするage age2 = 18; // Error ageはintではない

これまでのtypedefやusingではこのような事は出来ない

Page 357: Template Meta Programming入門から応用まで

その他付録

オーバーロード等も有効になる

int f(int);age f(age);

別物として扱われる

Page 358: Template Meta Programming入門から応用まで

その他付録

N3730Specializations and namespaces

Page 359: Template Meta Programming入門から応用まで

その他付録

ネストされた名前空間を閉じなくても特殊化を書けるようにする提案

Page 360: Template Meta Programming入門から応用まで

その他付録namespace A { namespace B { /* ... */ class C { /* ... */ }; }} // 一度名前空間を抜ける

namespace std { template<> // 特殊化を書く struct hash<A::B::C> { size_t operator()(A::B::C const &c) { /* ... */ } };}

namespace A { /* Reenter namespace I am using */ namespace B { /* ... */ }}

Page 361: Template Meta Programming入門から応用まで

その他付録namespace A { namespace B { /* ... */ class C { /* ... */ }; template<> struct ::std::hash<C> { std::size_t operator()(C const &c) { /* ... */ } }; /* ... */ }}

このように書けるようになる

Page 362: Template Meta Programming入門から応用まで

その他付録

N3728Packaging Parameter Packs

Page 363: Template Meta Programming入門から応用まで

その他付録

パラメータパックを保持するための型リストをサポートする提案

パラメータパックが間違いなく扱いやすくなる

具体例はN3728ペーパー参照

Page 364: Template Meta Programming入門から応用まで

その他付録

N3413Allowing arbitrary literal types for non-type template parameters

Page 365: Template Meta Programming入門から応用まで

その他付録

非型パラメータとして任意のリテラル型を許容しようという提案

Page 366: Template Meta Programming入門から応用まで

その他付録struct C { constexpr C(int v) : v(v) { } int v;};

template<C c> // !?struct X { int array[c.v];};

int main(){ X<C(42)> x;} C++の世界の法則が乱れる完全にヤバい提案

Page 367: Template Meta Programming入門から応用まで

その他付録

N3761Proposing type_at<>

Page 368: Template Meta Programming入門から応用まで

その他付録

パラメータパックのN番目の要素にアクセスする機能のメタ関数を標準に入れる提案

Page 369: Template Meta Programming入門から応用まで

その他付録簡単な実装案が書かれている要するにN番目の要素に到達するまで線形再帰する

template <unsigned N, typename T, typename ...R>struct type_at { using type = typename type_at<N - 1, R...>::type;};

template <typename T, typename ...R>struct type_at<0, T, R...> { using type = T;};

Page 370: Template Meta Programming入門から応用まで

その他付録簡単な実装案が書かれている要するにN番目の要素に到達するまで線形再帰する

template <unsigned N, typename T, typename ...R>auto value_at(T&&, R&&... r) -> decltype(auto) { return value_at<N - 1, R...>(std::forward<R>(r)...);}

template auto value_at(T&& t, R&&...) -> decltype(auto) { return std::forward<T>(t);}

Page 371: Template Meta Programming入門から応用まで

その他付録

対数オーダーで実装可能なのでAuthorに実装の改良を提案する意見を送付した

Page 372: Template Meta Programming入門から応用まで

その他付録

対数オーダーでの要素アクセスの実装

Page 373: Template Meta Programming入門から応用まで

その他付録

次のようなメタ関数を用意するtemplate<std::size_t N, class T = void>using make_type_sequence = typename make_type_sequence_impl<N, T>::type;

// make N-1 Ts type_sequence<T, T, ..., T> O(log2(N))

implでindex_rangeのように型列を対数オーダーで生成する

Page 374: Template Meta Programming入門から応用まで

その他付録

次のようなメタ関数を用意するtemplate<class T>struct type_wrapper{ using type = T;}; ただ型を保持するだけの型

Page 375: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type; }; 型リストを持つコンテナ型TとインデックスNを受け取る

Page 376: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type;}; type_wrapperに包んでTをimplに渡す

Page 377: Template Meta Programming入門から応用まで

その他付録

type_wrapperの役割・インスタンス化出来ない型も処理出来るようにする

Page 378: Template Meta Programming入門から応用まで

その他付録type_wrapperの役割

using type = typename decltype(impl(type_wrapper<T>()))::type;

例えばTがtemplate<class...> struct list; のようなインスタンス化不可能な型の場合

impl(list())はインスタンス化出来ずエラーになるがimpl(type_wrapper<T>())ならばインスタンス化出来て渡せる

Page 379: Template Meta Programming入門から応用まで

その他付録

type_wrapperの役割・トップレベルのcv修飾を保持する

Page 380: Template Meta Programming入門から応用まで

その他付録

type_wrapperの役割

impl(type_wrapper<T>())ならば値渡しの際もArgument

Deductionにおいて、Tのcv修飾情報が失われずに済む

Page 381: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type;}; template template parameterを使えばテンプレートクラスの持つ型リストを抽出する事が出来る

Page 382: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type;}; auto f() -> の形式の戻り値指定を使えば戻り値型部分でもparameter packを展開したり出来る

Page 383: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type;}; decltypeされる為だけに存在している関数であれば、関数定義は必要ない

Page 384: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type;}; またコンパイル時でもdecltypeするだけであればconstexpr修飾は必要無い

Page 385: Template Meta Programming入門から応用まで

その他付録

むしろconstexpr修飾された関数は暗黙にinline修飾される上inline修飾された関数の定義がない場合clang等は警告を出すのでconstexpr修飾はしないべき

Page 386: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type;}; 更にメタ関数を呼び出す

Page 387: Template Meta Programming入門から応用まで

その他付録template<std::size_t N, class... Types>struct type_at_impl{ using type = decltype(type_at_impl_impl< make_type_sequence<(N)> >::eval(static_cast< Types* >(nullptr)...) );};

type_sequence<void, void, void, ..., void>とN-1個のvoidを持つ型を対数オーダーで生成してテンプレートパラメータとして次の処理関数に渡す

Page 388: Template Meta Programming入門から応用まで

その他付録template<std::size_t N, class... Types>struct type_at_impl{ using type = decltype(type_at_impl_impl< make_type_sequence<(N)> >::eval(static_cast< Types* >(nullptr)...) );};

nullptrを受け取ってきた型リストの型のポインタにキャストしながら展開して次の処理関数に引数として渡す

Page 389: Template Meta Programming入門から応用まで

その他付録template<std::size_t N, class... Types>struct type_at_impl{ using type = decltype(type_at_impl_impl< make_type_sequence<(N)> >::eval(static_cast< Types* >(nullptr)...) );};

Typesはtype_wrapper<T>形式の型が入ったパラメータパックなのでその要素は必ずポインタにキャスト出来る

Page 390: Template Meta Programming入門から応用まで

その他付録template<std::size_t N, class... Types>struct type_at_impl{ using type = decltype(type_at_impl_impl< make_type_sequence<(N)> >::eval(static_cast< Types* >(nullptr)...) );};

更に実装の無い関数を呼び、decltypeを行う

Page 391: Template Meta Programming入門から応用まで

その他付録

template<class... Types>struct type_at_impl_impl<type_sequence<Types...>>{ template<class T> static T eval(Types*..., T*, ...);};

evalはテンプレートパラメータと関数引数の両方を受け取るdecltypeされる事が目的の実装の無い関数

Page 392: Template Meta Programming入門から応用まで

その他付録

template<class... Types>struct type_at_impl_impl<type_sequence<Types...>>{ template<class T> static T eval(Types*..., T*, ...);};

TypesはN-1個のvoid型だからstatic_cast<Types*>(nullptr)...としてevalに渡された引数は手前からN-1個までのものはvoid*

という扱いで受け取られる(type erasureが働く)

Page 393: Template Meta Programming入門から応用まで

その他付録template<class... Types>struct type_at_impl_impl<type_sequence<Types...>>{ template<class T> static T eval(Types*..., T*, ...);};

Tはtype_wrapper<元のコンテナの型リストのN番目の型>に推論されるtype_wrapperに包まれているのでN番目の型のcv修飾情報は欠落しない

Page 394: Template Meta Programming入門から応用まで

その他付録

template<class... Types>struct type_at_impl_impl<type_sequence<Types...>>{ template<class T> static T eval(Types*..., T*, ...);};

残りの余分な引数はellipsisに受け取られるので結果として関数の戻り値型をTにすればdecltypeされた時にTを得る

Page 395: Template Meta Programming入門から応用まで

その他付録template<class T, std::size_t N>struct type_at{private: template<template<class...> class Type, class... Args> static auto impl(type_wrapper<Type<Args...>>) -> typename type_at_impl<N, type_wrapper<Args>...>::type; public: using type = typename decltype(impl(type_wrapper<T>()))::type;}; 最終的に::typeでtype_wrapper<元のコンテナの型リストのN

番目の型>の中身である、元のコンテナの型リストのN番目の型が得られる

Page 396: Template Meta Programming入門から応用まで

その他付録

補足decltype(expression)::typeはwell-formed

Page 397: Template Meta Programming入門から応用まで

その他付録

この手法はNが大きい場合は有効であるが、Nが小さい場合は複雑な実装のメタ関数より線形実装の方が良い場合もある

Page 398: Template Meta Programming入門から応用まで

その他付録実際type_atではNが小さい場合が多そうなので悩ましいという話になっている

が、とりあえず次のrevisionでこのような問題についても取り上げて貰える予定である

標準化による結果としてコンパイラマジックによるO(1)の実現というのもあり得るだろうがやはりオーダー自体は重要である

Page 399: Template Meta Programming入門から応用まで

その他付録

この方法は同様にしてint,int,int...などのパラメータパック生成とconstexpr関数の組み合わせでvalue_atの実装にも適用出来る(つまりvalue_atも対数オーダー実装が可能)

Page 400: Template Meta Programming入門から応用まで

その他付録

実装は

怜-toki-などを見て欲しいhttps://github.com/fimbul/toki

Page 401: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 402: Template Meta Programming入門から応用まで

今回、コンパイル時に行われるメタプログラミングのポテンシャル、型を扱うプログラミングというもののイメージ

Template Meta Programmingの有用性について少しでも伝わっていれば嬉しいです

まとめ

Page 403: Template Meta Programming入門から応用まで

Template Meta Programmingのメリット・型を扱うプログラミングを行える・型検査でバグを実行前の段階で検出する・コンパイル時計算(実行時の処理を減らす)

・工夫でパフォーマンス向上(ET、遅延評価)

など

まとめ

Page 404: Template Meta Programming入門から応用まで

Template Meta Programmingのデメリット・酷使すればコンパイル時間が長くなる・実装に実行時とは異なる技術知識が必要・不慣れだとデバッグがつらい(特にgcc)

 (膨大なコンパイルエラーメッセージ)

・半分実装して途中経過を見るみたいな 事が難しいので脳内コンパイルも必要など

まとめ

Page 405: Template Meta Programming入門から応用まで

デバッグ方法・static_assert

・実行時に結果を標準出力・実態のない型をインスタンス化する (エラーメッセージで型を見る)

・mpl::print(必ずしも上手くはいかない)

など

まとめ

Page 406: Template Meta Programming入門から応用まで

スライドの内容はTemplate Meta Programming

の世界のたかだか氷山の一角に過ぎません

まとめ

Page 407: Template Meta Programming入門から応用まで

世の中にはラムダ式(Boost.MPL)やレイトレーシング(Sprout)等もTMP(with constexpr)

での実装例がありますし、Metaparseのような(闇の)ライブラリもあります(コンパイル時haskellコンパイラ的なサムシングなど)

まとめ

Page 408: Template Meta Programming入門から応用まで

入門から応用までなどと謳ったものの結局殆ど難しいことはろくに取り上げられず申し訳ないです、簡単な内容だけで結構な量になってしまっていたこともあり正直もっと応用的な内容にまで手が回りませんでした

まとめ

Page 409: Template Meta Programming入門から応用まで

その実装だけで本一冊書けてしまう、TMP

の世界で最も有名であろうBoost.MPLのようなライブラリを一切取り上げられなかったのは残念です

まとめ

Page 410: Template Meta Programming入門から応用まで

代わりに参考書籍を紹介します

まとめ

Page 411: Template Meta Programming入門から応用まで

まとめBoost.MPLの解説書

・主にMPLの実装にまつ わる話など・TMPの汎用テクニック・やや情報は古い (C++03向け)

・邦訳もあるはず

Page 412: Template Meta Programming入門から応用まで

まとめ

・Template関連本で本当 によく紹介されてい るので多分良書だと 思います・こちらもC++03向け・すいません自分は まだ読めてません

Page 413: Template Meta Programming入門から応用まで

まとめ

TC++PL 4th Edition

・C++11に対応した最新 のTC++PL

・Templateの本というわ けではない

Page 414: Template Meta Programming入門から応用まで

スライドの誤り等あれば教えて下さい

まとめ

きっとバグあります…

Page 415: Template Meta Programming入門から応用まで

ご清聴ありがとうございました

時間がおしていなければ質疑応答に移ります(おしてたら後で個人的にお願いします)

まとめ

Page 416: Template Meta Programming入門から応用まで

おしながき

1. Templateの基本確認2. Template Meta Programmingとは3. Template Meta Programming入門4. Template Meta Programming応用5. その他付録6. まとめ7. 質疑応答

Page 417: Template Meta Programming入門から応用まで

ありがとうございました

終わり