如何使 shared_ptr 包装器 class 与 make_shared 一起工作

How to make shared_ptr wrapper class work with make_shared

这个问题扩展了 Customising std::shared_ptr or boost::shared_ptr to throw an exception on NULL dereference

我想要一个行为类似于 shared_ptr 的 class,但在取消引用 nullptr 时会抛出异常。在上面的问题中,建议创建一个包含 shared_ptr 的包装器 class,并让该包装器抛出异常。

不过,我还想继续使用 make_shared。有没有办法让 make_shared 与我的(或任何)shared_ptr 的包装器 class 一起工作?按照

行事的东西
checked_shared_ptr<MyClass> csp = make_checked_shared<MyClass>(...);

添加合适的构造函数

最简单的解决方案是向 template<class T> class checked_shared_ptr 添加一个构造函数,以便可以使用 std::shared_ptr<T> 对其进行初始化,这将有效地编译以下内容(并执行预期的操作)。

checked_shared_ptr<MyClass> csp = std::make_shared<MyClass> (...);

实施示例

template<class T>
struct checked_shared_ptr {

  template<
    class U,
    class = decltype (std::shared_ptr<T> (std::shared_ptr<U> {}))
  > checked_shared_ptr (std::shared_ptr<U> const& src)
    : _sptr (src)
  { }

  // ...

  T& operator* () {
    if (_sptr)
      return *_sptr;

    throw std::runtime_error ("nullptr");
  }

  // ...

  std::shared_ptr<T> _sptr;
};

checked_shared_ptr<MyClass> csp = std::make_shared<MyClass> ();

decltype(std::shared_ptr<T> (std::shared_ptr<U>)) 的用法是构造函数仅在可以将 U* 转换为 T* 时才参与重载决策。