以下のコードは、コンパイルエラーになる:
template <class Iterator> Iterator f(const Iterator& it) { return it; } int main() { int ar[] = {1, 2, 3}; f(ar); // コンパイルエラー!呼び出し可能なf()のオーバーロードがない }
関数f()
はイテレータをconst
左辺値参照で受け取る。このようにした場合、テンプレートパラメータIterator
はint[3]
に推論される。C++の言語仕様として、組み込み配列はreturn
文で返せないので、コンパイルエラーになる(実際には、戻り値型のところでSFINAEが起きる)。
以下のように、イテレータをコピーで受け取ることで関数f()
を呼び出せるようになる:
template <class Iterator> Iterator f(Iterator it) { return it; } int main() { int ar[] = {1, 2, 3}; f(ar); // OK }
こうすることで、テンプレートパラメータIterator
はint*
に推論される。ポインタはreturn
文で返せるので、これは問題なく通る。
この変更が、C++14でのmake_move_iterator()
関数の仕様に適用された。
ちなみに、この推論ルールは、decay
(ディケイと読む)という名前で知られており、<type_traits>
ライブラリにはその推論ルールを適用するメタ関数が定義されている。