考虑一个示例,其中方法是纯虚拟的,采用模板类型的参数(从外部类型注入),并且该模板类型是本地类型(在函数体中定义)。这种情况会导致 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;
}
有人可以解释为什么这会导致编译错误吗?为什么它适用于非本地类型但不适用于本地类型?为什么非纯虚方法可以工作,而纯虚方法却不行?
我正在使用 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++ bug,在某种程度上与旧的 C++98 对使用本地类作为模板参数的限制有关
// C++98 标准
14.3.1/2:本地类型、无链接的类型、未命名类型或由任何这些类型组合而成的类型不得用作
模板类型参数的模板参数。
在 C++11 中,这个限制已被取消。正如您所注意到的,Visual Studio 可以正确编译它,Clang 也是如此。作为解决方法,添加抽象函数的定义适用于 g++
template<typename T>
void Outer<T>::InnerBase::foo(T const&) {};
实例 http://coliru.stacked-crooked.com/a/a340548561f8829c.
我认为你应该提交一份错误报告 http://gcc.gnu.org/bugs/ to g++.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)