在派生类中使用模板化基类中的typedef / using

时间:2013-11-06 15:48:23

标签: c++ templates inheritance c++11 typedef

在使用模板化基类从基类访问using时,如果没有别的话,我会遇到详细问题。在下面的代码中,派生类尝试使用其基类中的my_type

template <typename T>
class Base {
    public:
        using mytype = T;
};

template <typename T>
class Derived : public Base<T>{
    public:
        // using the base's mytype here
        static typename Base<T>::mytype func() { return 0;}
};

然而,在实践中,我发现这是一个非常多的角色,看起来它应该更简单。如果Base类没有模板化,那么它就不需要<T>或类型名称(显然)。

在我的真正问题中,我有很多来自基础的类,如果可能的话我想简化它。我现在所拥有的就像下一个例子,我只是添加一个额外的using来从基类中获取类型,但感觉就像一个额外的层,我不应该这样做需要有。

template <typename T>
class Derived : public Base<T>{
    public:
        using base_type = typename Base<T>::mytype;
        static base_type func() { return 0;}
};

这似乎是一个愚蠢的问题,但在派生类中使用基类mytype的次数使得它在前一种情况下非常可怕。是否有正确的方法从模板化基础中获取类型以保持可读性?

2 个答案:

答案 0 :(得分:13)

这是一个众所周知的语言怪癖,没有真正的解决方案。模板中的查找是在两个单独的步骤中完成的,在查找的第一阶段实例化之前实例化非依赖名称被解析为它们的含义,而在第二阶段中,依赖名称在之后被解析 em> instantiation。

这两个阶段的划分包含在语言中,以便为模板开发人员提供一些理解,而模板开发人员不知道模板将在何处实例化。第一阶段的查找是在定义模板的位置完成的,开发人员可以在这一点上对其进行推理。在某个时刻,模板将执行依赖于参数的操作,并且在模板定义的地方无法解析,因为模板参数尚未修复。这些名称被认为是依赖的,并且在替换模板参数后,查找被推迟到第二阶段,以便ADL可以启动。

这与您的特定问题有何关系?当您从非模板库继承时,开发人员已经修复了基础,并且可以按照您的预期在模板定义的位置查找。但是当基础依赖于模板参数时,基本的定义在派生模板定义的位置是未知的。特别是,在不替换类型的情况下,编译器不可能知道是否存在针对该特定类型的特化。这意味着在第一阶段,编译器不能对基数做任何假设,因此查找不能搜索到它。

在base中使用typedef的直接方法是让派生模板的开发人员明确地告诉编译器它想要一个类型,并且在实例化中定义 类型。基础模板。这里的关键点是编译器对基础知之甚少,但开发人员可以要求使用此模板符合基础的实例化必须的契约有嵌套类型。开发人员可以自由地为她的模板类型添加约束,编译器不是。

该语法是第一个块中的一个:typename Base<T>::type来引用类型,它告诉编译器使用合同要求使用T来实例化{{1}用户需要确保Derived将包含类型为Base<T>的嵌套成员type。简而言之,您可以选择第二种方法:创建一个可在typename内找到的本地typedef并解决该问题。在这种情况下,第一阶段的定期查找将找到嵌套的typedef,确定它引用了一个从属名称,并推迟了第二阶段的完整查找。

虽然这不能解决是否存在更好的方式(可读性方面)的问题,但我希望它提供了一些理解为什么事情就像它们一样。设计语言时的决定并不是随意的[可能或不理想,有些人认为第一阶段是不必要的和不需要的,但它不是任意的]

答案 1 :(得分:5)

也许我在这里遗漏了一些明显的东西,但您可以直接在该类型上使用using而无需为其命名:

template <typename T>
class Derived : public Base<T>{
public:
    using typename Base<T>::mytype;
    static mytype func() { return 0;}
};

您甚至可以决定using - mytype的声明是否应该进入publicprotectedprivate部分。