模板,内部结构,本地类型和纯虚函数,哦 [英] Templates, inner structs, local types, and pure virtual functions, oh my
问题描述
#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&) {};
I think you should submit a bug report to g++.
这篇关于模板,内部结构,本地类型和纯虚函数,哦的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!