C++11で新たに加わった Perfect Forward は,非常に便利な機能である.
template<class T> void f(T && x) { g(std::forward<T>(x)); // 別の関数 g に処理を丸投げする }
しかしこれは,多重定義された関数で使われた場合,予期せぬ挙動を示すことがある.
例を見てみよう. http://ideone.com/TxoeLv
#include <iostream> template<class T> void f(T &&) { std::cout << "f(T &&)\n"; } void f(std::string const&) { std::cout << "f(std::string const&)\n"; } int main() { std::string x; f(x); std::string const y = ""; f(y); }
結果:
f(T &&) f(std::string const&)
この例では,同じ std::string
型の値に対して,同じ関数 f
が呼ばれたにも関わらず,
const
の有無により,実際に呼ばれる関数の種類が変化している.
ここでは具体的に書くことはしないが, Perfect Forward を使っていると,それ以外のケースでも ミスが かなり起きやすい.
よって,少なくとも,以上のコードが何故そのような挙動になるかを説明できない人は,
多重定義された関数で Perfect Forward を使ってはいけない.
多重定義されていない関数では比較的マシだが,それでも寿命問題など落とし穴は多い.
Perfect Forward 自体, C++ の規格に 相当 熟達しているという自信がない限りは,扱うべきではないだろう.
この機能はライブラリ実装者向けのものだ.
追記 (22:50)