(comp.std.c++ でこの質問のバリエーションを尋ねましたが、回答が得られませんでした。)
f(arg)
このコードの への呼び出しが の const ref オーバーロードを呼び出すのはなぜf
ですか?
void f(const std::string &); //less efficient
void f(std::string &&); //more efficient
void g(const char * arg)
{
f(arg);
}
私の直感は、f(string &&)
オーバーロードを選択する必要があることを示しています。なぜならarg
、一時的なものに変換する必要があり、一時的なものは左辺値の参照よりも右辺値の参照によく一致するからです。
これはGCC とMSVC では発生しません (編集: Sumant に感謝: GCC 4.3-4.5 では発生しません)。少なくともG++ とMSVC では、作成された中間の一時変数がある場合でも、左辺値は右辺値参照引数にバインドされません。実際、const ref オーバーロードが存在しない場合、コンパイラはエラーを診断します。f(arg + 0)
ただし、 orを書くと、期待どおりに右辺値参照のオーバーロードf(std::string(arg))
が選択されます。
f(string &&)
C++0x 標準を読んだところ、const lvalue ref 引数を渡すときと同様に、実行可能かどうかを検討するときに、const char * から文字列への暗黙的な変換を考慮する必要があるようです。セクション 13.3 (オーバーロードの解決) では、あまりにも多くの場所で右辺値参照と const 参照を区別していません。また、中間の一時がある場合、左辺値が右辺値参照 (13.3.3.1.4/3) にバインドされないようにする規則は適用されないようです。結局のところ、一時から移動することは完全に安全です。
これは:
- 実装された動作が意図された動作である標準を誤解/誤解していますが、私の例がそのように動作する正当な理由がありますか?
- コンパイラベンダーが何らかの形で犯した間違いですか? それとも、一般的な実装戦略に基づく間違いですか? または、他のベンダーによってコピーされた、たとえば GCC (この左辺値/右辺値参照バインディング規則が最初に実装された場所) の間違いですか?
- 標準の欠陥、または意図しない結果、または明確にする必要があるものはありますか?
編集: 関連する追加の質問があります: C++0x 右辺値参照 - 左辺値-右辺値バインディング