c++11templatesstlpolicy-based-design

Use of unique_ptr in classes with protected destructors


I am studying policy based design from Modern C++ Design, and I have got stuck in a simple example below, where I was trying to use a std::vector of std::unique_ptrs in my templated policy class:

#include <memory>
#include <vector>

template <class T> struct MyPolicy {
  MyPolicy() = default;
  MyPolicy(std::size_t N) : myvec{std::vector<std::unique_ptr<T>>(N)} {
    for (std::size_t i = 0; i < N; i++)
      myvec[i].reset(new T(i));
  }

  // protected: // or, even, public:
  //   /*virtual*/ ~MyPolicy() = default;

private:
  std::vector<std::unique_ptr<T>> myvec;
};

template <class T, template <class> class Policy>
struct Shell : public Policy<T> {
  Shell() = default;
  Shell(std::size_t N) : Policy<T>(N) {}
};

int main(int argc, char *argv[]) {
  Shell<double, MyPolicy> s;
  s = Shell<double, MyPolicy>(7);

  Shell<double, MyPolicy> s2{6};
  s = std::move(s2);
  return 0;
}

Everything works well above. However, the catch is that since MyPolicy is supposed to be inherited from, its destructor needs to be either virtual and public, or non-virtual and protected (at least, quoting from the book).

In the above example, whenever I uncomment the lines to make them either

public:
virtual ~MyPolicy() = default;

or

protected:
~MyPolicy() = default;

the code does not compile. I cannot understand what the problem related to std::unique_ptr is in this example, since the type T is not incomplete or something that has a protected/private destructor.

I would appreciate your help. Thanks.


Solution

  • Declaring a destructor prevents the move constructor and move assignment operators from being implicitly declared. As such, if you declare a virtual destructor and want the default special move functions, you need to explicitly declare them yourself:

    public:
      virtual ~MyPolicy() = default;
      MyPolicy(MyPolicy&&) = default;             //here
      MyPolicy& operator= (MyPolicy&&) = default; //and here
    

    Live demo