First, I know that in pimpl design with std::unique_ptr, the destructor of the client class cannot be inline and needs to be implemented in the implementation file because the unique_ptr destructor needs a complete type for the pointed-to type. I already read the following pages:

Is std::unique_ptr required to know the full definition of T?

Why is "error: invalid application of 'sizeof' to an incomplete type using unique_ptr" fixed by adding an empty destructor? [duplicate]

My question is different.

Here is my code:

someclass.h:

#include <memory>
class SomeClass {
public:
  void do_some_thing();
  ~SomeClass();
  SomeClass();

private:
  class SomeClassImp;
  std::unique_ptr<SomeClassImp> ptr;
};

someclass.cpp:

#include "someclass.h"
#include <iostream>

// TODO: place before definition of SomeClassImp is also ok, why?
// SomeClass::~SomeClass() = default;
// SomeClass::SomeClass() = default;


// Why dtor here is also compiling ok? Here SomeClassImp is not a complete type
// actually if we print SomeClassImp using sizeof(..) inside the dtor, the compiling will fail requiring a complete type of SomeClassImp. 
// Then why is the compile ok with the unique_ptr requirements that the SomeClassImp type
// should be complete here?
SomeClass::~SomeClass(){};
SomeClass::SomeClass(){};


class SomeClass::SomeClassImp {
public:
  void implementation() { std::cout << "implementing...\n"; }
};
void SomeClass::do_some_thing() { ptr->implementation(); }
// following code is ok, it's understandable since here the SomeClassImp type is complete

// SomeClass::~SomeClass() = default;
// SomeClass::SomeClass() = default;
// following code is also ok

// SomeClass::~SomeClass(){};
// SomeClass::SomeClass(){};

----Edit-----

After some experiments, it has something to do with the template function's two stage name lookup rules:

  • std::unique_ptr is a template class, so its destructor is dependent on the template parameter
  • The name lookup rules apply to the destructor and will be instantiated after the compiler has already known all definitions in the same translation unit.

Above might be the reason why it compiles.

0

There are 0 best solutions below