Consider the following pair of mutually referencing types:
struct A;
struct B { A& a; };
struct A { B& b; };
This can be initialized with aggregate initialization in GCC, Clang, Intel, MSVC, but not SunPro which insists that user-defined ctors are required.
struct {A first; B second;} pair = {pair.second, pair.first};
Is this initialization legal?
slightly more elaborate demo: http://ideone.com/P4XFw
Now, heeding Sun's warning, what about classes with user-defined constructors? The following works in GCC, clang, Intel, SunPro, and MSVC, but is it legal?
struct A;
struct B { A& ref; B(A& a) : ref(a) {} };
struct A { B& ref; A(B& b) : ref(b) {} };
struct {B first; A second;} pair = {pair.second, pair.first};
demo: http://ideone.com/QQEpA
And finally, what if the container is not trivial either, e.g. (works in G++, Intel, Clang (with warnings), but not MSVC ("pair" unknown in initializer) or SunPro ("pair is not a structure")
std::pair<A, B> pair(pair.second, pair.first);
From what I can see, §3.8[basic.life]/6
forbids access to a non-static data member before lifetime begins, but is lvalue evaluation of pair.second "access" to second? If it is, then are all three initializations illegal? Also, §8.3.2[dcl.ref]/5
says "reference shall be initialized to refer to a valid object" which probably makes all three illegal as well, but perhaps I'm missing something and the compilers accept this for a reason.
PS: I realize these classes are not practical in any way, hence the language-lawyer tag. Related and marginally more practical old discussion here: Circular reference in C++ without pointers