【问题标题】:Templates, inner structs, local types, and pure virtual functions, oh my模板、内部结构、局部类型和纯虚函数,哦,我的
【发布时间】:2013-09-24 23:56:44
【问题描述】:

考虑一个示例,其中方法是纯虚拟的,采用模板类型的参数(从外部类型注入),并且该模板类型是本地类型(在函数体中定义)。这种情况会导致 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;
}

有人可以解释为什么这会导致编译错误吗?为什么它适用于非本地类型而不适用于本地类型?为什么非纯虚方法有效,纯虚方法无效?

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

来自 g++ 的确切错误是:

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

【问题讨论】:

  • @John:我不认为这个问题是重复的,因为它只适用于 C++98/03,而不适用于 C++11(本地类型可以是模板参数)。此外,它没有解释纯虚拟行为与非纯虚拟行为。

标签: templates c++11 g++ pure-virtual


【解决方案1】:

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

// C++98 标准

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

在 C++11 中,此限制已被取消。正如您所注意到的,Visual Studio 可以正确编译它,Clang 也是如此。作为一种解决方法,添加抽象函数的定义适用于 g++

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

Live Example.

我认为你应该向 g++ 提交bug report

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-04
  • 1970-01-01
  • 2012-02-18
  • 2014-03-08
  • 1970-01-01
  • 2020-01-30
相关资源
最近更新 更多