class SessionImpl;
class Session
{
public:
Session() = default;
virtual ~Session() = default;
private:
std::unique_ptr<SessionImpl> pImpl_;
};
이 코드를 빌드하면 visual studio 에서 아래 오류가 발생한다.
오류 C2027 정의되지 않은 형식 'SessionImpl'을(를) 사용했습니다.
경고 C4150 불완전한 형식 'SessionImpl'에 대한 포인터를 삭제했습니다. 소멸자가 호출되지 않습니다.
오류 C2338 can't delete an incomplete type
이유는 SessionImpl 이 전방선언되어 있고 Session의 생성자/소멸자가
SessionImpl의 정의를 알 수 없기 때문이다.
Session의 ctor와 dtor 를 default 키워드를 사용해 정의를 생략했는데,
이 경우 Session.cpp에서 SessionImpl.h를 include 하더라도 위 오류가 발생한다.
Session의 ctor와 dtor 정의 앞에 SessionImpl의 정의가 오면된다.
Session.h 는 아래 처럼 default를 제거하고
class SessionImpl;
class Session
{
public:
Session();
virtual ~Session();
private:
std::unique_ptr<SessionImpl> pImpl_;
};
Session.cpp 에 ctor와 dtor 정의를 작성하면 자연스럽게 해결된다.
#include "Session.h"
#include "SessionImpl.h"
Session::Session()
{
}
Session::~Session()
{
}
정리해보면 pimpl 관용구의 이점을 위해 전방선언했지만, ctor/dtor를 default 키워드로 정의하다보니 발생한 오류이다.
pimpl 관용구의 사용목적상 전방선언을 유지하기 위해 ctor/dtor의 default키워드를 사용하지 않으면되는 문제다.
번외로, Visual Studio 오류 창에서 C2338 can't delete an incomplete type 를 따라 들어가보면
memory 헤더에서 assert 된 지점을 볼 수 있는데
이 부분에서 unique_ptr의 소멸처리 구현부가 sizeof(_Ty)를 통해 사이즈를 확인하므로
템플릿 인자의 정의 유무를 체크하는 부분이 재밌것 같다.
// TEMPLATE CLASS default_delete
template<class _Ty>
struct default_delete
{ // default deleter for unique_ptr
constexpr default_delete() _NOEXCEPT = default;
template<class _Ty2,
class = typename enable_if<is_convertible<_Ty2 *, _Ty *>::value,
void>::type>
default_delete(const default_delete<_Ty2>&) _NOEXCEPT
{ // construct from another default_delete
}
void operator()(_Ty *_Ptr) const _NOEXCEPT
{ // delete a pointer
static_assert(0 < sizeof (_Ty),
"can't delete an incomplete type");
delete _Ptr;
}
};
참고 :
https://stackoverflow.com/questions/44633726/circular-dependency-cant-delete-an-incomplete-type
'Programming > C&C++' 카테고리의 다른 글
[C/C++] Comma Operator 콤마 연산자 (0) | 2022.06.17 |
---|---|
c++ 에서 timestamp 문자열 생성하기 (yy-mm-dd hh:mm:ss.ms) (0) | 2021.08.20 |
전문가를 위한 c++ 개정4판 오탈자 등록 (0) | 2021.05.07 |
C++ Korea 제5회 세미나 후기 (0) | 2019.04.08 |
[C++] std::list unique (0) | 2017.06.26 |