问题
I am apparently misunderstanding how the C-ish feature of simultaneously "declaring" and referring to a type using struct X
works in C++. (Plus I don't even know what this feature is called, properly.) I have three examples below to show what I'm doing but the main question is: Why is the nested type, forward declared in this way, at global scope instead of in class scope?
This works to forward declare a nested struct:
#include <memory>
class Foo1
{
Foo1();
~Foo1();
struct Impl;
std::auto_ptr<Impl> m_pimpl;
};
struct Foo1::Impl
{
Impl(){}
~Impl(){}
};
Foo1::Foo1(){}
Foo1::~Foo1(){}
int main() {}
So now I want to save a few characters by using a half-remembered C feature, so see where I've dropped the line struct Impl;
and for the field declared its type as auto_ptr<struct Impl>
instead of auto_ptr<Impl>
:
#include <memory>
class Foo2a
{
Foo2a();
~Foo2a();
std::auto_ptr<struct Impl> m_pimpl;
};
struct Foo2a::Impl
{
Impl(){}
~Impl(){}
};
Foo2a::Foo2a(){}
Foo2a::~Foo2a(){}
int main() {}
Here the compiler complains that no struct named 'Impl' in 'Foo2a'
. Sure enough, it is at global scope, as this compiles:
#include <memory>
class Foo2b
{
Foo2b();
~Foo2b();
std::auto_ptr<struct Impl> m_pimpl;
};
struct Impl
{
Impl(){}
~Impl(){}
};
Foo2b::Foo2b(){}
Foo2b::~Foo2b(){}
int main() {}
What's up with that? a) Why does it work at all to "declare" the type Impl
this way, and b) given that it works, why is Impl
at global scope not class scope?
And, BTW, declaring the field as auto_ptr<struct Foo2c::Impl>
doesn't work either.
回答1:
The scope of a name first declared as elaborated-type-specifier depends on the way in which it is used.
If you do struct Impl;
the struct is declared as a member of whatever scope that declaration occurs in, as in your first example. But in any other context, it's declared in the nearest enclosing block or namespace (but not class), as in the second and third examples.
The solution is just to forward-declare it as struct Impl;
in the class prior to any other uses. You can just refer to it as Impl
after that.
See [basic.scope.cdecl]/7 for the detailed rules.
来源:https://stackoverflow.com/questions/37712725/use-of-struct-foo-in-field-decl-doesnt-forward-declare-nested-class