#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; }
现在,如果在推断的上下文中,类型可以派生为Derived,如b的完全有效的声明所示.但是,如果我尝试引用Derived本身声明中的Type,那么我得到一个编译器错误,告诉我Type不指定一个类型(例如,如果别名的定义被取消注释).
我想这是与编译器无法检查的类型是否可以从基类中拉入,当解析Derived定义在特定的参数T的具体实例的上下文时,这是有关的.在这种情况下,这是令人沮丧的,因为基本总是定义类型,不管T.所以我的问题是双重的:
1).为什么在地球上这样会发生?这就是为什么编译器会在实例化上下文之外的所有外部解析Derived(我猜不推断上下文),而不这样做会避免这些“伪造”的编译器错误?也许这是一个很好的理由.标准中规定这是必须发生的规则是什么?
2).对于这种类型的问题,什么是一个很好的解决方法?我有一个现实生活中的情况,我需要在派生类的定义中使用基类类型,但是由于这个问题,我没有这样做.我想我正在寻找某种“隐藏在非推论上下文”的解决方案,在那里我通过将所需的定义/ typedef放在模板化类或者沿着这些行的东西之上来阻止这个编译器的第一遍.
编辑:正如下面的一些答案所指出的,我可以使用Alias = typename Base< T> :: Type.我应该从一开始就说过,我知道这个工作.然而,它不完全令人满意,原因如下:1)它不使用继承层次结构(Derived不必从Base派生为此工作),我正在尝试使用在我的基类层次结构和2)实际情况实际上有几层继承.如果我想从几层中抽出一些东西,这将变得非常丑陋(我需要参考一个非直接的祖先,或者重复使用在每一层,直到我达到我需要的)
解决方法
typename Base<T>::Type
您的别名应该如下定义:
using Alias = typename Base<T>::Type;
请注意,编译器在此时不知道Base< T> :: type是否描述成员变量或嵌套类型,这就是为什么需要关键字typename.
图层
你不需要在每一层重复定义,这里是一个例子,link:
template <typename T> struct intermediate : Base<T> { // using Type = typename Base<T>::Type; // Not needed }; template <typename T> struct Derived : intermediate<T> { using Type = typename intermediate<T>::Type; };
更新
你也可以使用自己的类,这依赖于使用unknown specializations.
template <typename T> struct Derived : Base<T> { using Type = typename Derived::Type; // <T> not required here. };