Рассмотрим приведенный ниже код:
#include<iostream>
template<typename T>
struct A{
using type = typename T::type;
};
// #1
struct B{
using type = int;
A<B>::type value;
};
int main() {
}
Я использую некоторые правила, которые нашел в стандарте, для проверки правильности кода, во-первых, точки создания экземпляра, потому что class B
не является шаблоном и A
- это шаблон класса, поэтому будет применяться следующее правило, а именно:
[temp.point # 4]
В противном случае точка создания экземпляра для такой специализации немедленно предшествует объявлению или определению области пространства имен , которое относится к специализации.
Это означает, что точка создания экземпляра для A<B>
предшествует определению of class B
, вероятно, это #1
в моем коде. Что касается здесь, я сталкиваюсь с вопросом, а именно: в точке #1
имя B
не может быть найдено. Я задерживаю вопрос и продолжаю под go оставшуюся часть раздела [temp.point] (Иногда оставшаяся часть раздела может разрешить некоторые недоразумения). Я нахожу цитату, которая, вероятно, относится к этому вопросу:
[temp.point # 7]
Контекст создания экземпляра выражения , который зависит от аргументов шаблона, представляет собой набор объявлений с внешней связью, объявленных до момента создания экземпляра специализации шаблона в той же единице перевода.
Здесь typename T::type
кажется квалифицированным идентификатором, но не выражением идентификатора. Значит, это не удовлетворяет предварительному условию. Однако typename T::type
является зависимым типом. Зависимое разрешение имен таково:
[temp.dep.res # 1]
При разрешении зависимых имен учитываются имена из следующих источников:
- Объявления, которые видны в точке определения шаблона.
- Объявления из пространств имен, связанных с типами аргументов функции, как из контекста создания ([temp.point]), так и из контекста определения.
Здесь второе правило не рассматривается, потому что это не вызов функции. Если я правильно понимаю первое правило, это означает, что имя B
должно быть объявлено до точки определения class template A
. Итак, мне интересно, как имя B
можно найти в точке создания экземпляра для A<B>
? даже B::type
. На данный момент я не нашел ни одной цитаты, которая могла бы это интерпретировать. Если я что-то пропущу или неправильно понимаю стандарт, поправьте меня.
Кроме того, все три компилятора согласны, что код законный .