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.
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.
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.