C++テンプレートの型推論
C++のテンプレートの動作について、確認のつもりでちょっといろいろやってみたら、いままで知らなかった動作に出会えた。
template<class T> T op(T (*fun)(T, T), T s1, T s2) { return (*fun)(s1, s2); }; template<class T> T add(T s1, T s2) { return s1 + s2; };
とテンプレートを定義しているとき、
op<int>(add<int>, 1, 1); op(add, 1, 1);
は、どちらもコンパイルできるし、テンプレートの型推論が働いて両者は等価になる。これはC++のテンプレートの動作としてちゃんと定義されている。
で、opの型とその引数の型をより自由にするために、
template<class T1, class T2, class T3> T1 op(T1 (*fun)(T2, T3), T2 s1, T3 s2) { return (*fun)(s1, s2); };
とすると、
op(add, 1, 1);
では op の型(もしくは *add の型)が分からないので、当然エラーになる。この場合、
op<int, int, int>(add, 1, 1); op(add<int, int, int>, 1, 1);
のどちらかにするのが、お行儀の良いやりかた。
ところがC++のテンプレートの型推論は思ってたよりも優秀で、
op<int>(add, 1, 1);
でも、ちゃんとコンパイルが通った。これはすごい。全ての型が推論できないときは、型引数全てを与えなければいけないものだと思っていたら、そうでもなかった。省略された型引数のみを型推論するこの動作は、関数のデフォルト引数の動作に良く似ている。
コレ、型引数の追加を忘れていてたまたま出会ったもの。失敗とは偉大だ。
ちなみに、
op(add<int>, 1, 1);
はエラー。