use of “struct Foo” in field decl doesn't forward declare nested class

做~自己de王妃 提交于 2019-12-12 01:46:41

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!