なぜうまくいかないのか
コンパイラーf()
はイテレーター・タイプで解決することを期待します。どうやら、それ(gcc 4.1.2)はそれをしません。
もしそうならそれは素晴らしいだろう!ただし、次のようfor_each
に宣言された関数テンプレートです。
template <class InputIterator, class UnaryFunction>
UnaryFunction for_each(InputIterator, InputIterator, UnaryFunction );
テンプレート控除UnaryFunction
では、呼び出し時にタイプを選択する必要があります。ただしf
、特定のタイプはありません。オーバーロードされた関数であり、f
タイプが異なるが多数あります。現在for_each
、テンプレートの推定プロセスを支援する方法はありません。必要なものを指定することによりf
、テンプレートの推定は失敗します。テンプレートの控除を成功させるには、呼び出しサイトでさらに作業を行う必要があります。
それを修正するための一般的な解決策
ここ数年、そしてC ++ 14後を期待しています。static_cast
(使用する「修正」によりテンプレートの推定が成功するf
が、正しいものを「修正」するためにオーバーロードの解決を手動で行う必要がある)を使用する代わりに、コンパイラーを機能させたいと考えています。f
いくつかの引数を求めたいと思います。可能な最も一般的な方法では、それは次のとおりです。
[&](auto&&... args) -> decltype(auto) { return f(std::forward<decltype(args)>(args)...); }
入力するのは大変ですが、この種の問題は迷惑なほど頻繁に発生するため、マクロ(溜息)でラップするだけです。
#define AS_LAMBDA(func) [&](auto&&... args) -> decltype(func(std::forward<decltype(args)>(args)...)) { return func(std::forward<decltype(args)>(args)...); }
そしてそれを使う:
void scan(const std::string& s) {
std::for_each(s.begin(), s.end(), AS_LAMBDA(f));
}
これは、コンパイラがしたいことを正確に実行します-名前f
自体にオーバーロード解決を実行し、正しいことを行います。これf
は、フリー関数かメンバー関数かに関係なく機能します。