У меня есть следующий код:
#include <iostream>
template <typename T>
struct Base
{
using Type = int;
};
template <typename T>
struct Derived : Base<T>
{
//uncommmenting the below cause compiler error
//using Alias = Type;
};
int main()
{
Derived<void>::Type b = 1;
std::cout << b << std::endl;
return 0;
}
Теперь имя Type
доступно для Derived
, если оно находится в выведенном контексте, как показано в действительном объявлении b
. Однако, если я попытаюсь ссылаться на Type
внутри объявления самого Derived
, то я получаю сообщение о компиляторе, сообщающее мне, что Type
не указывает тип (например, если определение Alias
раскоментировано),
Я думаю, что это связано с тем, что компилятор не может проверить, может ли быть извлечен Type
из базового класса, когда он анализирует определение Derived
вне контекста конкретного экземпляра параметр T
. В этом случае это расстраивает, так как Base
всегда определяет Type
независимо от T
. Поэтому мой вопрос двоякий:
1). Почему на Земле это происходит? Под этим я подразумеваю, почему компилятор беспокоит синтаксический анализ Derived
вообще вне контекста инстанцирования (я предполагаю, что не выведенный контекст), когда это не делается, избегайте этих ошибок "компилятора" фига? Возможно, для этого есть веская причина. Каково правило в стандарте, которое утверждает, что это должно произойти?
2). Что является хорошим обходным решением для такого рода проблем? У меня есть реальный случай, когда мне нужно использовать типы базового класса в определении производного класса, но я не могу этого сделать. Я предполагаю, что я ищу какое-то "спрятанное за невыделенным контекстом" решение, где я предотвращаю "первый проход" этого компилятора, помещая необходимые определения /typedef за шаблонные классы или что-то в этих строках.
РЕДАКТИРОВАТЬ: Как следует из некоторых ответов ниже, я могу использовать using Alias = typename Base<T>::Type
. Я должен был сказать с самого начала, я знаю, что это работает. Однако это не совсем удовлетворительно по двум причинам: 1) он вообще не использует иерархию наследования (Derived
не нужно выводить из Base
, чтобы это работало), и я точно пытаюсь использовать типы, определенные в моей иерархии базового класса, и 2) реальный случай фактически имеет несколько уровней наследования. Если бы я хотел извлечь что-то из нескольких слоев, это станет действительно довольно уродливым (мне нужно либо обратиться к непрямому предку, либо повторить using
на каждом уровне, пока не достигнет того, в котором я нуждаюсь)