Templates 模板、内部结构、局部类型和纯虚拟函数

Templates 模板、内部结构、局部类型和纯虚拟函数,templates,c++11,g++,pure-virtual,Templates,C++11,G++,Pure Virtual,考虑一个示例,其中一个方法是纯虚拟的,采用模板类型的参数(从外部类型注入),模板类型是本地类型(在函数体中定义)。此场景在g++下会导致编译时错误。诚然,这是一个非常极端的情况,但它确实源于真实的代码。下面是一个可编译、可复制的示例: #include <cstdio> template<typename T> struct Outer { struct InnerBase { virtual void foo(T const&)

考虑一个示例,其中一个方法是纯虚拟的,采用模板类型的参数(从外部类型注入),模板类型是本地类型(在函数体中定义)。此场景在g++下会导致编译时错误。诚然,这是一个非常极端的情况,但它确实源于真实的代码。下面是一个可编译、可复制的示例:

#include <cstdio>

template<typename T>
struct Outer
{
    struct InnerBase
    {
        virtual void foo(T const&) = 0;
        virtual void bar(T const&) {  };
    };

    struct InnerDerived : public InnerBase
    {
        void foo(T const&) override { std::printf("virtual call foo() worked\n"); }
        void bar(T const&) override { std::printf("virtual call bar() worked\n"); }
    };

    InnerBase* inner;
    Outer() : inner(new InnerDerived()) {  }
};


struct NonLocalStruct { };

int main()
{
    struct LocalStruct { };

    Outer<NonLocalStruct> a;
    Outer<LocalStruct>    b;

    a.inner->foo(NonLocalStruct());     // fine
    a.inner->bar(NonLocalStruct());     // fine
    b.inner->foo(LocalStruct());        // causes error
    b.inner->bar(LocalStruct());        // fine

    return 0;
}
#包括
模板
结构外部
{
结构内基
{
虚空foo(T常数&)=0;
虚空条(T常数&){};
};
结构InnerDerivated:公共InnerBase
{
void foo(T const&)重写{std::printf(“虚拟调用foo()已工作\n”);}
void bar(T const&)重写{std::printf(“虚拟调用栏()工作\n”);}
};
内底*内底;
外部():内部(新的内部派生()){}
};
结构非局部结构{};
int main()
{
结构LocalStruct{};
外部a;
外b;
a、 内部->foo(NonLocalStruct());//很好
a、 内部->栏(NonLocalStruct());//很好
b、 内部->foo(LocalStruct());//导致错误
b、 内部->栏(LocalStruct());//很好
返回0;
}
有人能解释为什么这会导致编译错误吗?为什么它适用于非本地类型而不适用于本地类型?为什么非纯虚拟方法有效而非纯虚拟方法无效

我正在使用g++4.8.1和-std=c++11(我也在VS2010中尝试过这个示例,它编译和运行时没有错误)

g++的确切错误是:

test.cpp:8:16:错误:“void Outer::InnerBase::foo(const T&)[with T=main()::LocalStruct]”,已使用但从未定义,该声明使用了本地类型“const main()::LocalStruct”[-fpermissive]


我猜这是一个g++错误,它与旧的C++98限制使用本地类作为模板参数有关

//C++98标准

14.3.1/2:本地类型、无连接类型、未命名类型或由这些类型中任何一种组合而成的类型不得用作 模板类型参数的模板参数

在C++11中,此限制已取消。正如您所注意到的,VisualStudio正确地编译了它,Clang也正确地编译了它。作为一种解决方法,添加抽象函数的定义可以与g一起工作++

template<typename T>
void Outer<T>::InnerBase::foo(T const&) {};
模板
void Outer::InnerBase::foo(T const&){};


我认为你应该向g++提交一个问题。

可能重复的@John:我不认为这个问题是重复的,因为它只适用于C++98/03,而不适用于C++11(其中本地类型可以是模板参数)。而且,它也不能解释纯虚拟行为和非纯虚拟行为的区别。事实证明,这是真的!谢谢