ムラサメ研究ブログ

主にゲームやプログラミングのログ

右辺値参照~完全転送まで100%理解するぞ! part5 参照の圧縮(reference collapsing)

右辺値参照の山場の一つ Universal Referenceまであと一歩

参照の圧縮とは

UniversalReferenceそのものだが

参照は(const等のストレージクラス除き)2種類しかない

X& (左辺値参照)、X&&(右辺値参照)

X&&& 等はエラーですし X& && 等、参照を重ねる事は出来ない

でも、templateを使うと不運にも参照が重なる事がある

template<class T>
void hoge(T& t){
}

例えばこのようなテンプレートに X&型の変数を適用したら T&は X& & になり、参照が重なってしまう これらの参照が重なった時はどうなるのだろうか?

コンパイルエラーにすると、テンプレートに参照を渡すものがほとんど動かなくなる C++では当然 参照が重なった場合に明確な法則がある

#include <iostream>

using namespace std;

class X{
public:
    X(){
    }
     X(X& x){
        cout << "copy" << endl;
    }
     X(X&& x){
        cout << "move" << endl;
    }
};

int main()
{
    using Y=X&;
    using Z=X&&;

    X x;

    X( (Y&)x );
    X( (Y&&)x );
    X( (Z&)x );
    X( (Z&&)x );

}


----

copy
copy
copy
move

template 以外に typedef (using) でも参照を重ねる事が出来るので 試してみた

結果は X& & -> X&

X& && -> X&

X&& & -> X&

X&& && -> X&&

と、結論からいえば すべて右辺値参照の時のみ右辺値参照。それ以外は左辺値参照となる

このことを 参照の圧縮(reference collapsing) と呼ぶ