多重定義された関数で C++11 の Perfect Forward を使ってはいけない

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)