右辺値参照~完全転送まで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) と呼ぶ