Действителен ли следующий код?
struct B{ using X=int; };
struct D1:B{ using X=X; }; // (1)
struct D2:B{ typedef X X; }; // (2)
Я ожидал бы, что точка объявления D2 :: X будет между двумя X в (2), но кажется, что gcc 4.8 и clang 3.2 принимают это.
Это стандартное поведение? Ссылки на рабочий проект / стандарт приветствуются.
Была дискуссия о том, using X = X
должен подобрать существо X
или X
это потенциально уже было в рамках. Чтобы избежать «неизвестных типов» и сделать его похожим на typedef
было определено, что существо определено X
не виден в выражении типа, который должен быть назначен (так, а не быть похожим на int x = x
, похоже на typedef x x;
).
Напомним, что typedef
это просто нормальное объявление с typedef
добавлено ключевое слово Первое упоминание о X
ничего не объявляет, просто говорит, какой тип будет псевдонимом. Это главное отличие using X = X
который мог объявлять X
ранее, если комитет решил так.
Обратите внимание, однако, ваш код имеет фактически неопределенное поведение, потому что это нарушает правило, которое не требует обязательной диагностики. 3.3.7p1b2
Имя N, используемое в классе S, должно относиться к тому же объявлению в его контексте и при повторной оценке в завершенной области действия S. Для нарушения этого правила не требуется никакой диагностики.
В typedef
декларация, окончательное имя объявляется, и это точка декларации. Итак, первый X
предшествует объявлению D2::X
и поэтому решает B::X
,