Инициализация объектов, ссылающихся друг на друга

Рассмотрим следующую пару взаимно ссылающихся типов:

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 ++ без указателей

19
задан Community 23 May 2017 в 11:45
поделиться