Reputation: 35992
In my original code, I refer to the third-party .H in the ClassOne
header file and everything works fine. Now, I received a new requirement that doesn't allow me to refer to the third-party .H in the ClassOne
header file. So that the consumer of my code (i.e. ClassOne) will not have to indirectly includes the third-party .H file. I have tried the following modification but it doesn't work.
Here is the sample code:
// third_party.h
struct PPP
{
int x;
int y;
}; // without default constructor
// Original code!
//////////////////////////////////////////////
// ClassOne.h // my class
#include <third_party.h> // refer to the .H in header file
namespace X
{
class ClassOne
{
...
private:
boost::scoped_ptr<PPP> m_scpPPP;
};
}
// ClassOne.cpp
#include <third_party.h>
namespace X
{
ClassOne::ClassOne()
{
m_scpPPP.reset( new PPP() ); // fine
}
...
}
// Modified code!
==========================================================
// ClassOne.h
struct PPP; // error C2371: 'PPP' : redefinition; different basic types
namespace X
{
class ClassOne
{
...
private:
boost::scoped_ptr<PPP> m_scpPPP;
};
}
// ClassOne.cpp
#include <third_party.h>
namespace X
{
ClassOne::ClassOne()
{
m_scpPPP.reset( new PPP() ); // now see errors.
// error C2512: 'PPP' : no appropriate default constructor available
}
...
}
Question 1> Where should I forward declare the third-party struct type PPP
?
Question 2> Why the compiler now complain about the PPP that has no default constructor?
Upvotes: 1
Views: 429
Reputation: 64253
It is not standard behavior to instantiate templates with incomplete types, therefore it shouldn't work boost::scoped_ptr
.
Having said that, unique_ptr
has a special rule, allowing to take incomplete types. If you use it (instead of boost::scoped_ptr
), then it is done like this :
// forward declaration of PPP, assuming c++ header
struct PPP;
namespace X
{
class ClassOne
{
...
private:
std::unique_ptr<PPP> m_scpPPP;
};
}
Upvotes: 1
Reputation: 17278
Simply put: That won't work. Since you use PPP (and not PPP*) in side your ClassOne, the compiler needs to know the size at that point, so it needs to know the definition of PPP. To hide PPP from the public .h file, you'll have to do more. One possible solution is to hide your implementation class behind another class. Another would be only to refer to PPP* in your class declaration (although that would make the usage of scoped_ptr<> a bit pointless).
The compiler expects a default constructor because he assumes there is one. He needs the definition of the class to call "new" as well. You can work around this problem by moving the implementation of the ctor to the .cpp file, where you may include thirdParty.h.
Upvotes: 0