ORNEW

Reference Collapsing 解説

Share on Facebook
Pocket

規格の文面はすべてドラフトn4606から引用しています。

Reference Collapsingとは

Reference CollapsingはC++11から導入された機能である。それ以前の規格では存在しない。

「参照の参照を作ることができる」という記述をインターネットで稀に見かけるが、これは厳密には間違いである。実際は「参照の参照が作られた時、正しい参照に変える」機能である。確かに挙動的には参照の参照を作っているようにも見える。しかし参照の参照という型は従来通り作ることはできない。

§ 8.3.2/5

There shall be no references to references, no arrays of references, and no pointers to references.

参照の参照、参照の配列、参照へのポインタは、C++11以降でも禁止されているのである。そもそも参照の参照は存在する必要がない。参照と、参照への参照は同一視出来るからだ。

以下のコードを見てほしい。

typedef int& int_ref;
int_ref& x = y;

このコードはC++11に対応していないコンパイラはエラーを発生させるだろう。int_refへの参照を作ると、それは参照の参照になってしまうからだ。先述したとおり参照への参照は禁止されている。

しかし、C++11ではコンパイルエラーにはならない。これこそReference Collapsingと呼ばれる機能であり、本記事の主題である。

このコードを見ると確かに「参照の参照を作っている」と思うのもわかるが、ここでxの型は、int&である。すなわちただのintの参照である。Reference collapsingは、特定の条件下で参照の参照が生成された時に、正しい参照へと変換する機能のことである。

この変換が発生する条件は、以下の3種類の型に対して参照の参照が発生した場合である。

§ 8.3.2/6

If a typedef (7.1.3), a type template-parameter (14.3.1), or a decltype-specifier (7.1.6.2) denotes a type TR
that is a reference to a type T, an attempt to create the type “lvalue reference to cv TR” creates the type
“lvalue reference to T”, while an attempt to create the type “rvalue reference to cv TR” creates the type TR.

どの場合も、評価されるまで型がわからない状況である。

rvalue referenceにrvalue referenceが付与された場合のみrvalue referenceが生成され、それ以外は全てlvalue referenceへと変換される。

もしかしたらコンパイルエラーになる方が素直に感じるかもしれないが、以下のコードを考えてみて欲しい。

template< typename T >
void foo( T& ){}

int a = 0;
int& x = y;
foo<int&>(x);

このコードもC++03だとエラー、C++11だと動く。これは非常に厄介である。この例は作為的だが、テンプレートがどこで参照になり、どこで参照とくっついてしまうかなど、わからない。実際に、複雑なメタプログラミングをしていると、意図せぬところでこういう状況が起きてしまうことが多々あるのだ。

もし上記例のfooを、C++03で参照型を許可するように書き換えるなら以下のようになる。

#include <boost/type_traits/add_reference.hpp>
template< typename T >
void foo( typename boost::add_reference<T>::type ){}

非常に面倒くさいコードになった。boostを使っているところは一応自分でadd_reference相当のものを書くことはできる。問題なのは面倒くさいこと以上に、Argument Deductionが使えないということだ。

メタプログラミングは今やC++に無くてはならない存在である。標準ライブラリの実装はメタプログラミングのオンパレードであるし、そもそも標準ライブラリにメタプログラミングを補助するType Traitsまで整備されている。そういった状況下において、Reference Collapsingは非常に便利で強力な機能なのである。