在具有受保护的析构函数的类中使用unique_ptr

时间:2017-11-30 17:16:51

标签: c++11 templates stl policy-based-design

我正在研究来自Modern C++ Design的基于策略的设计,我在下面的一个简单示例中陷入困境,我试图在我的模板政策中使用std::vector std::unique_ptr类:

#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;
}

一切都很好。但是,问题是因为MyPolicy应该是继承的,所以它的析构函数需要是virtualpublic,或者非virtual和{{1} (至少,从书中引用)。

在上面的例子中,每当我取消注释行以使它们成为

protected

public:
virtual ~MyPolicy() = default;

代码无法编译。我无法理解在此示例中与protected: ~MyPolicy() = default; 相关的问题是什么,因为类型std::unique_ptr不完整或者具有受保护/私有析构函数。

感谢您的帮助。感谢。

1 个答案:

答案 0 :(得分:2)

声明析构函数可防止移动构造函数和移动赋值运算符被隐式声明。因此,如果您声明一个虚拟析构函数并希望使用默认的特殊移动函数,则需要自己明确声明它们:

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

Live demo