【问题标题】:Inner template classes inheritance内部模板类继承
【发布时间】:2019-10-11 20:49:11
【问题描述】:

我有以下代码:https://gist.github.com/PatrikValkovic/50329975f86e0328ff1f85fda17a23f3,此处为实时示例:http://cpp.sh/675a3

简而言之,我有内部类 B 的类 A 和应该从 B 继承的类 D。当类 D 在类 A 中声明时(如注释),该代码有效。但是,当我将声明移到 A 类之外(如示例中所示)时,编译器会抱怨 A<T>::B<U> 不是类型。语法有什么问题?

// Example program
#include <iostream>
#include <string>

using namespace std;

template<typename T>
class A
{
public:
    template<typename U>
    class B;    

    /*
    class D : public B<int>
    {
    public:
        void method2() {
            cout << "Method 2" << endl;
            this->method1();
        }
    };
    */

    class D;
};

template<typename T>
template<typename U>
class A<T>::B 
{
public:
    void method1() {
        T x;
        cout << "Method 1: " << x << endl;
    }
};

template<typename T>
class A<T>::D : public A<T>::B<int>
{
public:
    void method2() {
        cout << "Method 2" << endl;
        this->method1();
    }
};

int main()
{
  A<int>::D b;
  b.method2();
}

【问题讨论】:

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


    【解决方案1】:

    这是 C++ 语言中非常奇怪的边缘情况之一,有一个不寻常的修复。问题就在这里:

    template<typename T>
    class A<T>::D : public A<T>::B<int>
                           ^^^^^^^^^^^^
    

    问题是您正在尝试使用模板类B,它是A 内部的依赖名称(也就是说,B 是嵌套在依赖于模板参数的另一种类型中的模板,在这里,T)。默认情况下,C++ 不会将依赖名称视为类型名称或模板名称,您必须以不寻常的方式使用 template 关键字明确告诉编译器“是的,这是模板的名称” :

    template<typename T>
    class A<T>::D : public A<T>::template B<int>
                                 ^^^^^^^^
    

    这告诉 C++“在 A&lt;T&gt; 内部,您将找到一个名为 B 的模板类型。请使用带有参数 int 的模板。”

    这类似于您必须将 typename 关键字与依赖类型一起使用 - 它告诉编译器“是的,这是一个类型的名称。”这里,template 关键字告诉编译器“是的,这是模板的名称。”

    【讨论】:

    • 天哪。从未见过以这种方式使用template 关键字(尽管我也对模板模板参数感到惊讶)。我想一个人永远不会完全了解 C++。问题出现了——我们真的要使用这么复杂的语言吗?但这超出了问题的范围。你的回答很有效,非常感谢。
    • 为什么A&lt;T&gt; 不引用当前实例化?如果是,那么我认为A&lt;T&gt;::B&lt;int&gt;应该是正确的,因为“在类模板的定义中,类模板的嵌套类,类模板的成员,或者类的嵌套类的成员模板,类模板或嵌套类的注入类名,"。所以,因为B 是当前实例化A&lt;T&gt; 的成员,所以在我看来好像不需要::template
    • clang 的进一步调查表明我可能是对的。 GCC 不同意 Clang 和我的观点。但是,我强烈怀疑 GCC 错误地拒绝了他的代码(尽管我承认我已经有一段时间没有接触这个主题了)。
    猜你喜欢
    • 1970-01-01
    • 2011-08-26
    • 1970-01-01
    • 1970-01-01
    • 2018-05-23
    • 2012-11-15
    • 1970-01-01
    • 2018-01-18
    相关资源
    最近更新 更多