The code would work file as long as I don't move the definition of constructor (of B
) to the header B.h
.
B.h
class Imp; //<--- error here
class B{
public:
std::unique_ptr<Imp> imp;
B(); //<--- move definition to here will compile error
~B();
//// .... other functions ....
};
B.cpp
#include "B.h"
#include "Imp.h"
B::B(){ }
~B::B(){ }
Imp.h
class Imp{};
Main.cpp (compile me)
#include "B.h"
Error: deletion of pointer to incomplete type
Error: use of undefined type 'Imp' C2027
I can somehow understand that the destructor must be moved to .cpp
, because destructure of Imp
might be called :-
delete pointer-of-Imp; //something like this
However, I don't understand why the rule also covers constructor (question).
I have read :-
- Deletion of pointer to incomplete type and smart pointers
describes reason why destructor need to be in.cpp
. - std::unique_ptr with an incomplete type won't compile
warns about the default destructor.
Preprocessed out of b.cpp can be generated by following command,
g++ -E b.cpp >> b.preprocessed
And it is as follows,
It is clearly visible here, declaration of
class Imp
comes after constructor.So how constructor can create something which doesn't exist for it? (Only forward declaration is not enough) and It makes clear that constructor definition must be in
b.cpp
file so that it will come afterclass Imp
declaration and it becomes complete type.Other point is, i don't think it is the correct way of using pimple-idiom. Implementation class should be declared and defined in source file which is not accessible from outside rather then keeping it in separate header file.
The constructor needs to destroy the class members, in the case that it exits by exception.
I don't think that making the constructor
noexcept
would help, though maybe it should.