Любопытно взаимно повторяющиеся определения классов
Я хочу, чтобы объявления типов в двух классах взаимно зависели друг от друга. Вот первый пример, который компилируется как с clang, так и с gcc:
template <class Sum>
struct A
{
using X = char; // (1)
using Z = typename Sum::B::Y; // (2)
};
template <class Sum>
struct B
{
using Y = typename Sum::A::X;
};
struct AplusB
{
using A = ::A<AplusB>;
using B = ::B<AplusB>;
};
AplusB::A::Z z;
int main() {}
Тем не менее, есть интересный момент. Если вы меняете строки (1) и (2), то он не скомпилируется с ошибкой:
error: нет имени с именем "X" в "A"
Это заставляет меня сомневаться, действительно ли исходный код действителен в смысле стандарта С++, или просто так происходит компиляция?
Вот второй пример, который также использует порядок создания экземпляра шаблона:
template <class Sum>
struct A
{
using X = char;
using P = typename Sum::B::Q;
};
template <class Sum>
struct B
{
using Y = typename Sum::A::X;
using Q = int;
};
struct AplusB
{
using A = ::A<AplusB>;
using B = ::B<AplusB>;
};
AplusB::A::X z; // (1)
AplusB::B::Q t; // (2)
int main() {}
Здесь, если вы замените (1) и (2), он не скомпилируется с ошибкой:
ошибка: тип типа 'Q' в 'B'
Итак, возникает вопрос: действительно ли это разрешено стандартом для определений классов, которое зависит друг от друга?