Search code examples
c++nestednamespacesforward-declaration

How to forward declare a C++ struct in case nested namespaces are used?


I have following C++ code

A.h

namespace x {
namespace y {
namespace z {
   
struct Container;

class A
{
public:
    A(Container& _container);
    
    void info();
    
private:
    Container& container;
};

}
}
}

A.cpp

#include "A.h"
#include <iostream>

namespace x {
namespace y {
namespace z {

A::A(Container& _container) : container(_container) {}

void A::info() {
    std::cout << "Instance of A!" << std::endl;
}

}
}
}

Container.h

#include "A.h"

namespace x {
namespace y {
namespace z {

struct Container {

    Container(): a(*this) {}
    A a;
};

}
}
}

main.cpp

#include <cstdlib>
#include "Container.h"

int main(int argc, char** argv) {
    
    x::y::z::Container container;
    
    container.a.info();

    return 0;
}

The above mentioned code is compilable and workable.

But let's say I move the Container.h out of the z namespace and let it in the y namespace (nested in the x namespace). So the code will look like that

A.h

namespace x {
namespace y {
namespace z {
   
struct Container;

class A
{
public:
    A(x::y::Container& _container);
    
    void info();
    
private:
    x::y::Container& container;
};

}
}
}

A.cpp

#include "A.h"
#include <iostream>

namespace x {
namespace y {
namespace z {

A::A(x::y::Container& _container) : container(_container) {}

void A::info() {
    std::cout << "Instance of A!" << std::endl;
}

}
}
}

Container.h

#include "A.h"

namespace x {
namespace y {

struct Container {

    Container(): a(*this) {}
    x::y::z::A a;
};

}
}

main.cpp

#include <cstdlib>
#include "Container.h"

int main(int argc, char** argv) {
    
    x::y::Container container;
    
    container.a.info();

    return 0;
}

In that case the compilation fails with following error messages:

In file included from A.cpp:7:
A.h:26:22: error: expected ')' before '&' token
   26 |     A(x::y::Container& _container);
      |      ~               ^
      |                      )
A.h:31:11: error: 'Container' in namespace 'x::y' does not name a type
   31 |     x::y::Container& container;
      |           ^~~~~~~~~
A.cpp:14:5: error: expected constructor, destructor, or type conversion before '(' token
   14 | A::A(x::y::Container& _container) : container(_container)
      |     ^

Can anybody tell me why these error messages pop up in case I move the Container.h from the z namespace and let it in the y namespace nested in the x namespace?


Solution

  • The problem is that you never declared x::y::Container in A.h. You did declare x::y::z::Container, but that doesn't name the same type. Simply move the declaration into the y namespace:

    namespace y {
    namespace z {
       
    struct Container;
    

    Into ->

    namespace y {
    
    struct Container;
    
    namespace z {