2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ラムダ式でもSFINAE

Last updated at Posted at 2018-10-22

問題

ラムダ式をオーバーロード風に扱いたい場合など、ラムダ式でもSFINAEで呼び出しを制御したい場合がある
この際、どう書けばよいかについてまとめる

解決

通常の関数の場合から考えると

  • 引数部
  • 戻り値型部
  • テンプレート引数部
    の3種類が思いつく。これらについてひとつずつ考えていく

引数部でSFINAEする

引数の末尾にsfinaeするための部分を付ける
個人的にもっともおすすめ

例.cpp
std::visit(mylib::overload{
    [](std::string s){return s; },
    [](auto s, decltype(std::to_string(s))* =0){return std::to_string(s); }  //<--to_stringできる奴だけ
}, v);

[](auto s, /*SFINAEしたい項目*/ * =0){/*略*/; }
* = の2記号は間を開ける必要があることに注意(くっつけると *= に解釈されて文法ミスになる)

  • 利点
    • 戻り値型を明記しなくて済む
      • 戻り値型部でやる場合、戻り値型の推論が効かなくなるため自分で書く必要が出てくる
  • 欠点
    • 見た目が若干キモイ

戻り値部でSFINAEする

例.cpp
std::visit(mylib::overload{
    [](std::string s){return s; },
    [](auto s)->decltype(std::to_string(s)){return std::to_string(s); }  //<--to_stringできる奴だけ
}, v);

[](auto s)->/*SFINAEしたい項目+戻り値型*/{/*略*/ }

  • 利点
    • 上の例の様な「処理XができるかをSFINAEで調べて、できたら処理Xを呼ぶ」みたいなケース、その場合これの見た目が一番キモくない
      • ラムダ式でsfinaeを使う場合、このパターンは結構あると思われる
    • また、戻り値の型に興味がない場合でも
  • 欠点
    • 戻り値の型推論が利かなくなるため、SFINAEの条件と戻り値の型が全然違う場合、見た目がキモくなるor辛くなる
      • 要するに「汎用でない」

テンプレート引数部でSFINAEする

テンプレート引数部なんてものはラムダ式にない。したがってここでSFINAEする方法もない
少なくともC++17現在では

C++20ではラムダ式にもテンプレート引数部が存在するようになるといわれている

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?