无法从模板基类导入typedef

时间:2018-11-06 15:34:51

标签: c++ templates inheritance typedef using

此问题不是重复问题,而是后续问题 Propagating 'typedef' from based to derived class for 'template'

作为继承typedef的解决方案,建议使用using将它们导入派生类,而简单的using typename Base::typedefed_type应该足够。

以下代码大部分来自Roman Kruglov's answer

#include <vector>
template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
public:
    using typename A::Vec_t;
    // .........

private:
    Vec_t v;
};

int main()
{
B<int> bb;
}

但是它无法编译,因为编译器非常需要A的模板参数。

Intel编译器错误消息:

    1>C:\Work\EDPS\test_eigen\test_eigen.cpp(27): error : argument list for class template "A" is missing
1>      using typename A::Vec_t;
1>                     ^
1>          detected during instantiation of class "B<T> [with T=int]" at line 34
1>
1>C:\Work\EDPS\test_eigen\test_eigen.cpp(31): error : identifier "Vec_t" is undefined
1>      Vec_t v;
1>      ^
1>          detected during instantiation of class "B<T> [with T=int]" at line 34
1>

MVC错误消息:

 c:\work\edps\test_eigen\test_eigen.cpp(27): error C2955: 'A': use of class template requires template argument list
1>c:\work\edps\test_eigen\test_eigen.cpp(17): note: see declaration of 'A'
1>c:\work\edps\test_eigen\test_eigen.cpp(32): note: see reference to class template instantiation 'B<T>' being compiled
1>c:\work\edps\test_eigen\test_eigen.cpp(27): error C3210: 'A': a member using-declaration can only be applied to a base class member
1>c:\work\edps\test_eigen\test_eigen.cpp(32): warning C4624: 'B<int>': destructor was implicitly defined as deleted

那怎么了?我想念什么吗?还是那里的评论和答案有错??

2 个答案:

答案 0 :(得分:2)

只需对此进行修改

template<typename T>
class B : public A<T>
{
public:
    using typename A<T>::Vec_t;
    // .........

};

在C ++中,如果A是模板,则独立的A不是'complete'类型。您需要指定模板参数。这就是A<T>解决它的原因。

答案 1 :(得分:2)

我认为混淆是由A用作基类的方式引起的。如果类模板派生自具有模板参数的类模板,则必须完全限定基类名称。但是,如果类是从类模板专业化派生的,则可以使用不带模板参数列表的基类名称。

template<typename T>
struct A {
    using t = T;
};

template<typename T>
struct B : A<T> {
    using typename A<T>::t; // Full qualification needed -> mandatory argument list
};

struct C : A<int> {
    using typename A::t; // Injected class name -> optional argument list
};

Live on Coliru

此外,请注意,tC中直接可用,而无需使用声明或typedef。我可能仍然有用,例如,如果C是私下从A<int>继承而来的,但是您希望tC中是公开可用的(在示例中,{{1} }默认情况下是公开继承的,因为它是C