C++

C++11 任意の式によるSFINAE

  • このエントリーをはてなブックマークに追加
  • Pocket

C++11 テクニック #1

tl;dr

C++11から任意の式がSFINAEされるようになった。

ヤバ便利。

 

SFINAE

Substitution Failure Is Not An Error

実体化の失敗はエラーではない

という意味のC++専門用語。

 

テンプレートの実体化に失敗しても、

Overload Candidatesから外されるだけ。

他のオーバーロードが検索される。

テンプレートを無理やり条件分岐のように使うことができる。

実質的に任意に実体化を選択することが可能になる仕様である。

型制約

まず、前段階。

テンプレートに型制約をもたせることができる。

以下の関数は、テンプレートの実体化を整数型に制限する。

std::enable_if< cond, T >::type

はcondがfalseの場合実体化に失敗する。

condがtrueの場合はTに実体化する。

これを利用して実体化を制限できる。

 

クラスの場合

部分的特殊化が優先して実体化されるので、SFINAEする。

ついでに制約ではじかれたことが分かるように、

部分的特殊化が実体化に失敗したらプライマリテンプレートでstatic_assertする。

static_assert(false)はコンパイル時に常に評価されてしまうので、

型依存のbool式を使うのがポイント。

std::enable_ifの第2テンプレートパラメータはvoidがデフォルトなので省略。

 

型特性による実装の切り替え

C++11の奥義、SFINAEによる関数のオーバーロード。

型特性(型が可能とする操作)による関数の呼びわけ。

イテレータの種類によってアルゴリズムを切り替える場合を考えてみた。

 

ジェネリックな設計をする場合には、

このようなそびえ立つオーバーロードを乱舞させて、

複数のオーバーロードを呼び分けることもある。

実体化はひとつだけされなけばならない

複数のオーバーロードが実体化に成功すると、

オーバーロードが曖昧になる。

つまり、コンパイルエラーになるということだ。

よって、オーバーロードがふえるほど慎重にSFINAEを記述しなければならない。

SFINAEでは包含関係を表現できないので、つらい。

Conceptが必要だ。

 

decltypeによるSFINAE

decltypeはテンプレートに実体化の際に考慮される。

decltypeを用いるとある関数を適用できるかなどを簡潔に記述できる。

簡潔に…(´・_・`)

 

面倒なのでこのへんで

メタプログラミングでもっといろいろな使い方があると思うが、

全部書いてたらキリがない気がしてきたのでやめます。

 

  • このエントリーをはてなブックマークに追加
  • Pocket

コメントを残す

*