Slide 1

Slide 1 text

content = 落ち穂拾い"/> いなむのみたま いなむのみたま

Slide 2

Slide 2 text

Variabletemplatesfortraits Variabletemplatesfortraits

Slide 3

Slide 3 text

要するに_v 要するに_v メタ関数の_tと同様に、::valueを書かずにすむやつ。 例: ::valueは_tと違ってtypenameキーワードいらないので恩恵が⼩さい けど、まああれば使いますよね。 //sameasstd::is_same::value std::is_same_v

Slide 4

Slide 4 text

std::is_aggregate std::is_aggregate 型Tがaggregateかどうかを判定するメタ関数。 以上! Preconditions std::remove_all_extents_tが完全型であるか、 (cv修飾された)void型であること。

Slide 5

Slide 5 text

ところで…… ところで…… aggregateって知ってる? aggregateって知ってる?

Slide 6

Slide 6 text

aggregateの定義 aggregateの定義 型Tが集成体であるための条件は以下である: 型Tが集成体であるための条件は以下である: 1.ユーザー定義されたコンストラクタ、explicitなコンストラクタ、継承 コンストラクタを持たない 2.private∕protectedな⾮静的メンバ変数を持たない 3.仮想関数を持たない 4.仮想基本クラス、private∕protected基本クラスを持たない

Slide 7

Slide 7 text

aggregateだと aggregateだと 集成体初期化できる 集成体初期化できる structPoint{ intx,y; }; Pointa={1,2};//aggregate-initialization

Slide 8

Slide 8 text

集成体初期化の罠 集成体初期化の罠 **ユーザー定義された(uesr-provided)**コンストラクタ、explicitなコ ンストラクタ、継承コンストラクタを持たない ...定義? structWTF{ WTF()=delete;//定義ではない }; WTFa={};//well-formedinC++11/14/17

Slide 9

Slide 9 text

集成体初期化の罠 集成体初期化の罠 C++20 C++20 ユーザー定義されたコンストラクタ、explicitなコンストラクタ、継承コ ンストラクタを持たない ユーザ宣⾔されたコンストラクタまたは継承されたコンストラクタを持 たない。 structPoint{ WTF()=delete;//わたくし、宣⾔です }; WTFa={};//ill-formedinC++20

Slide 10

Slide 10 text

designatedinitialization designatedinitialization C++20 C++20 GNU拡張ではしれっと使えていた。 structPoint{ intx,y,z; }; //C++20feature:designatedinitialization Pointa={.x=1,.y=2,.z=0};

Slide 11

Slide 11 text

std::bool_constant std::bool_constant namespacestd{ template<boolB> usingbool_constant=integral_constant; }

Slide 12

Slide 12 text

std::bool_constant std::bool_constant example example いい例が思いつかないが・・・ クラスを場合分けで2つ書いて、std::ture_typeとstd::falseを別々に継承す るの⾯倒なので、直接条件を羅列したりするのに使えそう。 (ほんまに使うか?) template<class...Pred> structis_hoge :std::bool_constant<(Pred::value&&...)>{};

Slide 13

Slide 13 text

Logicaloperation Logicaloperation metafunctions metafunctions std::cunjunction std::disjunction std::negation std::cunjunction_v std::disjunction_v std::negation_v

Slide 14

Slide 14 text

クラス名で雰囲気を察せよ クラス名で雰囲気を察せよ

Slide 15

Slide 15 text

クラス名で雰囲気を察せよ クラス名で雰囲気を察せよ わかんない⼈絶対いる わかんない⼈絶対いる

Slide 16

Slide 16 text

conjunction=連⾔(れんげん) conjunction=連⾔(れんげん) つまり、∧論理積 つまり、∧論理積 disjunction=選⾔(せんげん) disjunction=選⾔(せんげん) つまり、∨論理積 つまり、∨論理積 negation=否定(ひてい) negation=否定(ひてい) つまり、¬論理否定 つまり、¬論理否定

Slide 17

Slide 17 text

std::conjuncion std::conjuncion B...の論理積を⾏うメタ関数。 ⼀般にはメタ述語AとB(あるいはもっとたくさん)のすべてを満たすか 判定したい場合などに使うはず。 namespacestd{ template structconjunction; template inlineconstexprbool conjunction_v=conjunction::value; }

Slide 18

Slide 18 text

std::conjuncion std::conjuncion example example いい例が思いつかないが・・・ パラメータパックの型がすべて同じことをSFINAEしたいときとかに使え そう。 template std::enable_if_t...>> func(Thead,P...tail){ //... }

Slide 19

Slide 19 text

std::conjuncion std::conjuncion indetail indetail テンプレート引数が空のとき、std::true_typeを基底クラスに持つ というテンプレート引数を持つとき、 がはじ めてfalseになる型を基底クラスに持つ がtrueのとき、 を基底クラスに持つ B , ..., B 1 n bool(B : i : value) B : n−1 : value B n

Slide 20

Slide 20 text

std::conjuncion std::conjuncion indetail indetail std::conjuncion_vは普通にbool。 static_assert( std::conjuncion, std::integral_constant >::value ==4);//OK

Slide 21

Slide 21 text

std::conjuncion std::conjuncion Tips Tips がはじめてfalseとなるとき であるような はそもそもvalueを持たなくて良い B : i : value j > i Bj static_assert( std::conjunction_v ==false);//OK

Slide 22

Slide 22 text

std::disjuncion std::disjuncion B...の論理和を⾏うメタ関数。 ⼀般にはメタ述語AとB(あるいはもっとたくさん)のどれかを満たすか 判定したい場合などに使うはず。 namespacestd{ template structdisjuncion; template inlineconstexprbool disjuncion_v=disjuncion::value; }

Slide 23

Slide 23 text

std::disjunction std::disjunction example example いい例が思いつかない、つらい・・・ 型Tのデフォルト値をなんやかんやする例。 template<classT> inlinestd::enable_if_t, std::is_aggregate>,T> default_v=[]{ ifconstexpr(std::is_aggregate_v){returnT{};} else{returnT();} }();

Slide 24

Slide 24 text

std::disjunction std::disjunction indetail indetail テンプレート引数が空のとき、std::false_typeを基底クラスに持つ というテンプレート引数を持つとき、 がはじ めてtrueになる型を基底クラスに持つ がfalseのとき、 を基底クラスに持つ B , ..., B 1 n bool(B : i : value) B : n−1 : value B n

Slide 25

Slide 25 text

std::disjunction std::disjunction indetail indetail std::disjunction_vは普通にbool。 static_assert( std::disjunction, std::integral_constant >::value==4);//OK

Slide 26

Slide 26 text

std::disjunction std::disjunction Tips Tips がはじめてtrueとなるとき であるような はそもそもvalueを持たなくて良い B : i : value j > i Bj static_assert( std::disjunction_v ==true);//OK

Slide 27

Slide 27 text

std::negation std::negation あるメタ述語Bの論理否定を⾏うメタ関数。 std::bool_constantを基底クラスに持つ。 メタ述語の否定のメタ述語を作りたいときに。 namespacestd{ template structnegation:bool_constant{}; template inlineconstexprbool negation_v=negation::value; }

Slide 28

Slide 28 text

std::negation std::negation example example std::conjunction,std::disjunctionのパラメータパック内でメタ述語 の否定をしたいときに使うのは想定されるよね。 メタ述語でなくいいなら!std::is_integral_v...と書ける。 template std::enable_if_t>...>> func(Ts...xs){//Ts...はすべて整数ではない型 //... }

Slide 29

Slide 29 text

TraitsforSFINAE-friendly TraitsforSFINAE-friendly swap swap 多次元配列のswapがnoexcept(false)になるCoreIssueの修正のために 提案された

Slide 30

Slide 30 text

引数が多次元配列のとき(つまりTが配列のとき)、swapがADLの候補 に上がらないのがおわかりだろうか? template voidswap(T(&a)[N],T(&b)[N]) noexcept(noexcept(swap(*a,*b)));

Slide 31

Slide 31 text

TraitsforSFINAE-friendlyswapの提案によて修正。 template voidswap(T(&a)[N],T(&b)[N]) noexcept(is_nothrow_swappable_v);

Slide 32

Slide 32 text

is_swappableの⼀族 is_swappableの⼀族 規格書のTable42—Typepropertypredicatesでひときわ⻑い説明が書い てあるので印象深い。 template<classT,classU> structis_swappable_with; template<classT> structis_swappable; template<classT,classU> structis_nothrow_swappable_with; template<classT> structis_nothrow_swappable;

Slide 33

Slide 33 text

is_swappable_with is_swappable_with usingstd::swap usingstd::swapされたという条件下かつ、 されたという条件下かつ、 未評価な⽂脈で 未評価な⽂脈で swap(declval(),declval()) swap(declval(),declval())と と swap(declval(),declval()) swap(declval(),declval())が が ともにwell-formedな式となるかを判定する。 ともにwell-formedな式となるかを判定する。 Preconditions 型TとUが、完全型であること。 もしくは(cv修飾された)voidか、要素数不明の配列型であること。

Slide 34

Slide 34 text

§23.15.4.3Type §23.15.4.3Type properties/C++17 properties/C++17 inTable42—Typepropertypredicates inTable42—Typepropertypredicates AccesscheckingisperformedasifinacontextunrelatedtoTandU. Onlythevalidityoftheimmediatecontextoftheswapexpressionsis considered. [Note:Thecompilationoftheexpressionscanresultinsideeffectssuch astheinstantiationofclasstemplatespecializationsandfunction templatespecializations,thegenerationofimplicitly-definedfunctions, andsoon.Suchsideeffectsarenotinthe immediatecontext andcan resultintheprogrambeingill-formed.—endnote]

Slide 35

Slide 35 text

cpprefjpより引⽤ cpprefjpより引⽤ このメタ関数はTとUについてのswap関数の直接のコンテキストの妥当 性(そのシグネチャで有効なswapがあるかどうか)のみをチェックす る。 そのため、結果がtrueとなったとしてもswap関数の呼び出しができるこ とは保証されない(その他の要因によりコンパイルエラーが発⽣する可 能性がある)。

Slide 36

Slide 36 text

別の⾔い⽅でもう⼀度 別の⾔い⽅でもう⼀度 シグネチャだけ⾒ると呼び出し可能だけども、(実際には)TやUの使⽤ によって、なんらかのテンプレートの実体化等やら暗黙に定義されたの 特殊メンバの⽣成なんやらをもろもろ起こした結果、それがなんらかの エラーとなるかもしれない。 そのような場合でもis_swappable_withはしっかりと実体化し、valueメ ンバ変数がtrueとなるかもしれないよ。

Slide 37

Slide 37 text

is_swappable is_swappable Tが参照可能な型であれば、valueメンバ変数は std::is_swappable_with::valueと同じ。 それ以外であればfalse。 Preconditions 型Tが完全型であること、 もしくは(cv修飾された)voidか、要素数不明の配列型であること。

Slide 38

Slide 38 text

is_nothrow_swappable is_nothrow_swappable is_nothrow_swappable is_nothrow_swappable 無例外保証検査がついてお得! 無例外保証検査がついてお得!

Slide 39

Slide 39 text

SFINAEとは SFINAEとは テンプレートの実体化に失敗しても即座にエラーとならず、他の実体化 を探しに⾏く仕様のこと。

Slide 40

Slide 40 text

SFINAE-friendlyとは SFINAE-friendlyとは テンプレートの実体化の際にハードエラーを起こさないように設計され ているという意味。

Slide 41

Slide 41 text

SFINAE-friendlyでないメタ関数 SFINAE-friendlyでないメタ関数 #include template structPlusResultT{ usingType =decltype(std::declval() +std::declval()); }; template usingPlusResult =typenamePlusResultT::Type;

Slide 42

Slide 42 text

SFINAE-friendlyなメタ関数 SFINAE-friendlyなメタ関数 #include //primarytemplate: template> structHasPlusT:std::false_type {}; //partialspecialization(maybeSFINAE daway): template structHasPlusT() +std::declval())>> :std::true_type {};

Slide 43

Slide 43 text

SFINAE-friendlyなメタ関数 SFINAE-friendlyなメタ関数 #include //primarytemplate, //usedwhenHasPlusTyieldstrue template::value> structPlusResultT{ usingType=decltype(std::declval() +std::declval()); }; //partialspecialization,usedotherwise template structPlusResultT{};

Slide 44

Slide 44 text

SFINAE-friendlyであるために SFINAE-friendlyであるために コンテキストが正しいかのみを確認する 結果の型を取りたい場合は先にコンテキストが正しいかを確認する そして致命的なエラーが起こる場合を特殊化する必要がある

Slide 45

Slide 45 text

参考⽂献 参考⽂献 ISO/IEC148822017 C++Templates:TheCompleteGuide-SecondEdition workingdraft http://eel.is/c++draft/dcl.init.aggr Adding[nothrow-]swappabletraits,revision3 http://www.open- std.org/jtc1/sc22/wg21/docs/papers/2016/p0185r1.html Stackoverlow:Whyisswappingmultidimensionalarraysnotnoexcept? https://stackoverflow.com/questions/26793979/why-is-swapping- multidimensional-arrays-not-noexcept