Рассмотрим следующую пару взаимно ссылающихся типов:
struct A;
struct B { A& a; };
struct A { B& b; };
Это может быть инициализировано с агрегированной инициализацией в GCC, Clang, Intel, MSVC, но не SunPro, который настаивает на том, что требуются определяемые пользователем ctors.
struct {A first; B second;} pair = {pair.second, pair.first};
Законна ли эта инициализация?
немного более сложная демонстрация: http://ideone.com/P4XFw
Теперь, учитывая предупреждение Sun, как насчет классов с определяемыми пользователем конструкторами? Следующее работает в GCC, clang, Intel, SunPro и MSVC, но законно ли это?
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};
демонстрация: http://ideone.com/QQEpA
И, наконец, что, если контейнер не является тривиальным либо, например (работает в G ++, Intel, Clang (с предупреждениями), но не в MSVC («пара» неизвестна в инициализаторе) или SunPro («пара не является структурой»)
std::pair pair(pair.second, pair.first);
Из того, что я вижу, §3.8 [ basic.life] / 6
запрещает доступ к нестатическому элементу данных до того, как начнется время жизни, но является ли lvalue оценка пары. second «доступ» ко второму? Если да, то все три инициализации незаконны? Кроме того, §8.3.2 [dcl.ref] / 5
говорит, что «ссылка должна быть инициализирована для ссылки на действительный объект», что, вероятно, также делает все три незаконными, но, возможно, я что-то упускаю, и компиляторы принимают это по какой-то причине.
PS: Я понимаю, что эти классы никоим образом не практичны, отсюда и тег language-lawyer. Связанное и несколько более практичное старое обсуждение здесь: Циркулярная ссылка на C ++ без указателей