Domanda

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.

È stato utile?

Soluzione

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.

Altri suggerimenti

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top