模板,内部结构,本地类型和纯虚函数,哦 [英] Templates, inner structs, local types, and pure virtual functions, oh my

查看:384
本文介绍了模板,内部结构,本地类型和纯虚函数,哦的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个例子,其中方法是纯虚拟的,接受模板类型的参数(从外部类型注入),并且模板类型是局部类型(在函数体中定义)。这种情况会导致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()working \\\
}
void bar(T const&)override {std :: printf(virtual call bar()working \\\
); }
};

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


struct NonLocalStruct {};

int main()
{
struct LocalStruct {};

Outer< NonLocalStruct>一个;
Outer< LocalStruct> b;

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

return 0;
}

有人可以解释为什么会导致编译错误?为什么它使用非本地类型,而不是本地类型?为什么非纯虚拟方法工作,但不是纯粹的?



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



g ++的确切错误是:


test.cpp:8:16:error:'void Outer :: InnerBase :: foo(const T&)[with T = main():: LocalStruct]', main():: LocalStruct',被使用但从未定义[-fpermissive]



解决方案

我的猜想是,这是一个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&){};

在线示例



我认为您应该提交 错误报告 添加到g ++。


Consider an example where a method is pure virtual, takes a parameter of a templated type (injected from an outer type), and that templated type is a local type (defined in a function body). This scenario causes a compile-time error under g++. Admittedly, this is quite a corner case, but it does originate from real code. Here's a compilable, reproducible example:

#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;
}

Can someone explain why this causes a compile error? Why does it work with non-local types but not local ones? Why do non-pure virtual methods work but not pure ones?

I'm using g++ 4.8.1 with -std=c++11 (I've also tried this example in VS2010 and it compiles and runs without errors).

The exact error from g++ is:

test.cpp:8:16: error: 'void Outer::InnerBase::foo(const T&) [with T = main()::LocalStruct]', declared using local type 'const main()::LocalStruct', is used but never defined [-fpermissive]

解决方案

My guess is that this is a g++ bug, that is somehow related to an old C++98 restriction on the use of local classes as template parameters

// C++98 Standard

14.3.1/2: A local type, a type with no linkage, an unnamed type or a type compounded from any of these types shall not be used as a template-argument for a template type-parameter.

In C++11, this restriction has been lifted. As you note, Visual Studio compiles this correctly, and so does Clang. As a work-around, adding the definition of the abstract function works with g++

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

Live Example.

I think you should submit a bug report to g++.

这篇关于模板,内部结构,本地类型和纯虚函数,哦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆