Upgrade to Pro — share decks privately, control downloads, hide ads and more …

nakameguro_feature.cpp vol17 落ち穂拾い:メタ関数編

Cranberries
March 14, 2019
360

nakameguro_feature.cpp vol17 落ち穂拾い:メタ関数編

Cranberries

March 14, 2019
Tweet

Transcript

  1. View Slide

  2. Variabletemplatesfortraits
    Variabletemplatesfortraits

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  7. aggregateだと
    aggregateだと
    集成体初期化できる
    集成体初期化できる
    structPoint{
    intx,y;
    };

    Pointa={1,2};//aggregate-initialization

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. std::bool_constant
    std::bool_constant
    namespacestd{
    templateboolB>
    usingbool_constant=integral_constant

    View Slide

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

    View Slide

  13. Logicaloperation
    Logicaloperation
    metafunctions
    metafunctions
    std::cunjunction
    std::disjunction
    std::negation

    std::cunjunction_v
    std::disjunction_v
    std::negation_v

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  18. std::conjuncion
    std::conjuncion
    example
    example
    いい例が思いつかないが・・・
    パラメータパックの型がすべて同じことをSFINAEしたいときとかに使え
    そう。
    template

    View Slide

  19. 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

    View Slide

  20. std::conjuncion
    std::conjuncion
    indetail
    indetail
    std::conjuncion_vは普通にbool。
    static_assert(
    std::conjuncion

    View Slide

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

    View Slide

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

    View Slide

  23. std::disjunction
    std::disjunction
    example
    example
    いい例が思いつかない、つらい・・・
    型Tのデフォルト値をなんやかんやする例。
    templateclassT>
    inlinestd::enable_if_t

    View Slide

  24. 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

    View Slide

  25. std::disjunction
    std::disjunction
    indetail
    indetail
    std::disjunction_vは普通にbool。
    static_assert(
    std::disjunction

    View Slide

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

    View Slide

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

    View Slide

  28. std::negation
    std::negation
    example
    example
    std::conjunction,std::disjunctionのパラメータパック内でメタ述語
    の否定をしたいときに使うのは想定されるよね。
    メタ述語でなくいいなら!std::is_integral_v...と書ける。
    template

    View Slide

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

    View Slide

  30. 引数が多次元配列のとき(つまりTが配列のとき)、swapがADLの候補
    に上がらないのがおわかりだろうか?
    template

    View Slide

  31. TraitsforSFINAE-friendlyswapの提案によて修正。
    template

    View Slide

  32. is_swappableの⼀族
    is_swappableの⼀族
    規格書のTable42—Typepropertypredicatesでひときわ⻑い説明が書い
    てあるので印象深い。
    templateclassT,classU>
    structis_swappable_with;

    templateclassT>
    structis_swappable;

    templateclassT,classU>
    structis_nothrow_swappable_with;

    templateclassT>
    structis_nothrow_swappable;

    View Slide

  33. is_swappable_with

    View Slide

  34. §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]

    View Slide

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

    View Slide

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

    View Slide

  37. is_swappable
    is_swappable
    Tが参照可能な型であれば、valueメンバ変数は
    std::is_swappable_with

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  41. SFINAE-friendlyでないメタ関数
    SFINAE-friendlyでないメタ関数
    #include

    template

    View Slide

  42. SFINAE-friendlyなメタ関数
    SFINAE-friendlyなメタ関数
    #include
    //primarytemplate:
    template

    View Slide

  43. SFINAE-friendlyなメタ関数
    SFINAE-friendlyなメタ関数
    #include
    //primarytemplate,
    //usedwhenHasPlusTyieldstrue
    template

    View Slide

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

    View Slide

  45. 参考⽂献
    参考⽂献
    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

    View Slide