右辺値の変換規則について
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あるやん。というか数日前にそれでなにがしかするとか書いてなかったっけ?忘れよう。