There is a compilation error in unique_ptr, and I don't know even if I look into it, so please let me ask you a question.
A.h
#include<memory>
class B;
class A {
public:
static std::unique_ptr<A>create();
private:
void init();
std::unique_ptr<B>_b;
};
A.cpp
#include "A.h"
# include "B.h"
std::unique_ptr<A>A::create(){
std::unique_ptr<A>ptr(new A);
ptr->init();
return ptr;
}
void A::init(){
_b=B::create();
}
B.h
#include<memory>
classB{
public:
static std::unique_ptr<B>create();
};
B.cpp
#include "B.h"
std::unique_ptr<B>B::create(){
std::unique_ptr<B>ptr(newB);
return ptr;
}
main.cpp
#include "A.h"
int main(void){
auto a = A::create();
return 0;
}
The following error will appear
clang++ A.cpp B.cpp main.cpp -std=c++11
In file included from main.cpp:1:
In file included from ./A.h:1:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/memory:2395:27: error: invalid application of 'sizeof' to an incomplete type 'B'
static_assert(sizeof(_Tp) > 0, "default_delete can not delete incomplete type");
^~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/memory:2603:13: note: in instantiation of member function 'std::__1::default_delete<B>::operator()' requested here
__ptr_.second()(__tmp);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/memory:2571:46: note: in instantiation of member function 'std::__1::unique_ptr<B, std::__1::default_delete<B> >::reset' requested here
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
^
./A.h:4:7: note: in instantiation of member function 'std::__1::unique_ptr<B, std::__1::default_delete<B> >::~unique_ptr' requested here
class A {
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/memory:2603:13: note: in instantiation of member function 'std::__1::default_delete<A>::operator()' requested here
__ptr_.second()(__tmp);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/memory:2571:46: note: in instantiation of member function 'std::__1::unique_ptr<A, std::__1::default_delete<A> >::reset' requested here
_LIBCPP_INLINE_VISIBILITY ~unique_ptr() {reset();}
^
main.cpp:4:12: note: in instantiation of member function 'std::__1::unique_ptr<A, std::__1::default_delete<A> >::~unique_ptr' requested here
auto a = A::create();
^
./A.h:2:7:note:forward declaration of 'B'
class B;
^
1 error generated.
If you include B.h instead of B's forward declaration in A.h, the error will not appear, but
Is this the only way to do it?
If you change to shared_ptr, there is no error.
When I looked it up with this error, I found that there were only topics related to Pimple.
Thank you for your cooperation.
c++ c++11
You can de-inline A's destructor as shown in the answer related to Simple.
A.h
#include<memory>
class B;
class A {
public:
static std::unique_ptr<A>create();
~A(); // De-Inline Destructors
private:
void init();
std::unique_ptr<B>_b;
};
A.cpp
#include "A.h"
# include "B.h"
std::unique_ptr<A>A::create(){
std::unique_ptr<A>ptr(new A);
ptr->init();
return ptr;
}
A::~A()=default;//Destructor de-inline
void A::init(){
_b=B::create();
}
Note:
All STL std::unique_ptr<T>
are defined inline as template classes, and delete T
ultimately calls the T
destructor.Therefore, T
(B
in the example question) must be defined and the destructor must be accessible.
There is also a way to use Pimpl, but if that's the case, separate it from the declaration without inline definition somewhere. If you want to narrow the scope of influence, do you want to separate std::default_delete<B>::operator()
?
std::unique_ptr<B>
in A.h.
namespace std{
template<>struct default_delete<B>{
constexpr default_delete()noexcept=default;
void operator() (B*ptr) const noxcept;
};
}
Specialize with and use B.cpp to
void std::default_delete<B>::operator()(B*ptr)const noxcept {deleteptr;}
can be defined as to separate dependencies with class B
.
As far as the description of Quoted from If type T is incomplete, operator() execution is ineligible. Therefore, I think it is a specification that the template unique_ptr
is concerned, the default_delete<T>
class, which is the second argument D of the template, seems to require that T
be complete.default_delete<T>
descriptionT
in unique_ptr
cannot be declared forward.
© 2024 OneMinuteCode. All rights reserved.