Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ circular dependency - namespace vs struct

Tags:

c++

namespaces

Please educate me. Why does this compile:

struct compiles
{
    struct A;
    struct B
    {
        B(const A &a) : member(a.member) { }
        int member;
    };
    struct A
    {
        A(const B &b) : member(b.member) { }
        int member;
    };
};

while this does not:

namespace doesnt
{
    struct A;
    struct B
    {
        B(const A &a) : member(a.member) { }
        int member;
    };
    struct A
    {
        A(const B &b) : member(b.member) { }
        int member;
    };
}

(in MSVC 9.0)

like image 360
Dead or Alive Avatar asked Feb 08 '11 21:02

Dead or Alive


3 Answers

The body of a class/struct/union definition is processed all at once, allowing references to members of classes defined later. A namespace is processed from top to bottom, and a forward declaration of struct A does not allow you to use its members without a definition. Try moving the definition of B's constructor out-of-class so you can put it after the definition of A.

like image 52
Jeremiah Willcock Avatar answered Nov 09 '22 22:11

Jeremiah Willcock


In C++, class scope is special. Any declaration that extends to or past then end of the class definition is automatically extended to the regions defined by its member definitions (3.3.6 [basic.scope.class]).

This means that in the first case both the first declaration of struct A and the full definition of struct A are visible in the body of B and its constructor.

This doesn't apply to namespace scope so in the second case a.member in the constructor of B is an error because a definition of struct A isn't yet visible.

like image 7
CB Bailey Avatar answered Nov 09 '22 21:11

CB Bailey


[Also tested with g++ 4.2] The first one compiles because the compiler fully picks up all the types defined within the struct before actually compiling the nested structures (think about public inline methods using private attributes that appear later within the class). Within the namespace the compiler simply works top-to-bottom and doesn't have special rules.

like image 3
Mark B Avatar answered Nov 09 '22 22:11

Mark B