次のコード スニペットがあります。これはまったく些細なことですが、より一般的なコードで使用しようとしているパターンを示しています。
template<typename InT, typename ResT>
ResT unary_apply( InT val, std::function<ResT(InT)> fn )
{
return fn(val);
}
関数ポインター、ファンクター、ラムダなどで unary_apply を呼び出せるようにしたいので、 を使用std::function
してすべてを抽象化します。
上記を次のように使用しようとすると、C++ (g++ 4.7) は関連する型推論を実行できません。
double blah = unary_apply( 2, []( int v ) { return 3.0 * v; } );
失敗する
src/fun.cpp:147:75: error: no matching function for call to ‘unary_apply(int, test()::<lambda(int)>)’
src/fun.cpp:147:75: note: candidate is:
src/fun.cpp:137:6: note: template<class InT, class ResT> ResT unary_apply(InT, std::function<ResT(InT)>)
src/fun.cpp:137:6: note: template argument deduction/substitution failed:
src/fun.cpp:147:75: note: ‘test()::<lambda(int)>’ is not derived from ‘std::function<ResT(double)>’
そして、テンプレート パラメーターを明示的に指定する必要があることがわかりました (実際には、推論できないのは戻り値の型だけだと思います)。
double blah = unary_apply<int, double>( 2, []( int v ) { return 3.0 * v; } );
私は C++11 の型推論規則にはあまり詳しくありませんが、上記の動作は妥当なように思えます ( の内部メカニズムによる推論std::function
は、おそらくかなり大きな課題であることがわかります)。私の質問は: 上記の関数を書き直しunary_apply
て同じ柔軟性を維持することは可能ですか (2 番目のパラメーターとして渡すことができる関数/ファンクターなどの型に関して)、型推論への手がかりをさらに与えます。呼び出し時にテンプレート パラメータを明示的に指定する必要はありませんか?