Question

Lets go for a walk with Bulldog :)

Say I have a namespace Street::House (inside namespace Street) where the class Bulldog is declared (let it be in House/Bulldog.hpp):

namespace Street {
namespace House {
class Bulldog {};
}
}

Then, I have the Bulldog.hpp:

#include "House/Bulldog.hpp"    

namespace Street {
using House::Bulldog;
}

Pay attention to what's going on: I'm injecting declaration of Street::House::Bulldog to the namespace Street as Street::Bulldog with using declaration.

Then, I have the Owner.hpp where the class Bulldog is forward declared:

namespace Street {
class Bulldog;

class Owner {
  Bulldog* bulldog;
};
}

Finally, I have the Owner.cpp:

#include "Owner.hpp"
#include "Bulldog.hpp"

namespace Street {
// Implementation of Owner...
}

Compilation error occurs in the Owner.cpp:

error: 'Bulldog' is already declared in this scope

The natural explanation of this phenomenon seems to be that C++ treats these 2 Bulldog classes as different, but why? I can't see any ambiguity in this case, i.e. it could actually work if properly implemented by compilers.

What workarounds can you suggest? One I can think of is to simply remove forward declaration of Bulldog from Owner.hpp and move #include "Bulldog.hpp" from Owner.cpp to Owner.hpp. However, this will result in exact inclusion rather than forward declaration.

Was it helpful?

Solution

It seems you can fix this by changing Bulldog.hpp to say

namespace Street {
    namespace House {
        class Bulldog;
    }
    using House::Bulldog;

    // ...
}

This works for me in Clang.

OTHER TIPS

Owner.hpp which you wrote as:

namespace Street {
class Bulldog;

class Owner {
  Bulldog* bulldog;
};
}

Should have instead been

namespace Street {
namespace House {
class Bulldog;
}

class Owner {
  House::Bulldog* bulldog;
};
}

You were accidentally forward declaring Street::Bulldog, which is not a real class, instead of Street::House::Bulldog, which is a real class. Therefore, your implementation in Owner.cpp was upset because Bulldog* was ambiguous. It doesn't know if you are referring to the declared class Street::Bulldog or the declared (and also defined, though the compiler doesn't care about that) Street::House::Bulldog.

Since the class you wanted to forward declare is Street::House::Bulldog, you need to include the second, House namespace in your declaration in the .hpp file.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top