У меня есть следующий код:
#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 на каждом уровне, пока не достигнет того, в котором я нуждаюсь)