右辺値の変換規則について
struct Foo { Resource* r_; Foo() r_(new Resource) {} Foo(Foo & foo) : r_(new Resource(*foo.r_)) {} // A Foo(Foo const & foo) : r_(new Resource(*foo.r_)) {} // B Foo(Foo && foo) : r_(foo.r_) {foo.r_ = nullptr;} // C Foo(Foo const && foo) : r_(new Resource(*foo.r_)) {} // D }; Foo ret_rval(); Foo const ret_rcval(); Foo & ret_lref(); Foo const & ret_lcref(); Foo && ret_rref(); Foo const && ret_rcref(); void f() { Foo lval; Foo const lcval; Foo & lref = val; Foo const & lcref = val; Foo && rref = val; Foo const && rcref = val; Foo copy1(lval); // A B C D Foo copy2(lcval); // B D Foo copy3(lref); // A B C D Foo copy4(lcref); // B D Foo copy5(rref); // A B C D Foo copy6(rcref); // B D Foo copy7(ret_rval()); // C D B Foo copy8(ret_rcval()); // D B Foo copy9(ret_lref()); // A B C D Foo copy10(ret_lcref()); // B D Foo copy11(ret_rref()); // C D B Foo copy12(ret_rcref()); // D B }
http://d.hatena.ne.jp/Cryolite/20080220#p1, http://d.hatena.ne.jp/faith_and_brave/20081023/1224755522 ほか。
N1377の中にあるサンプルコードのオーバーロードを値渡し以外で全て並べただけみたいな感じになってしまった。コメントのアルファベットは私が理解したオーバーロードのマッチ順に並べてある。合っているのかどうかは分からない。左のほうにあるオーバーロード関数が存在しなかった場合はその次の関数にマッチする。関数というかこの場合はコンストラクタだけど。あぁ、Foo::Foo(Foo)というコンストラクタがあれば、常に最優先でマッチする。関数の引数型が右辺値参照で、そこに渡す「式」が右辺値の場合にオーバーロード解決で優先して選択されると、そんな理解。うーん、手元にそれを確かめるものが…あぁ、gcc4.3あるやん。というか数日前にそれでなにがしかするとか書いてなかったっけ?忘れよう。