问题
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]
回答1:
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++.
来源:https://stackoverflow.com/questions/18994041/templates-inner-structs-local-types-and-pure-virtual-functions-oh-my