带有抽象接口的 CRTP,dynamic_cast 工作但 dynamic_pointer_cast 不工作

CRTP with abstract interface, dynamic_cast working but dynamic_pointer_cast does not

我正在考虑维基百科中 CRTP 的基本示例

#include <memory>

// Base class has a pure virtual function for cloning
class AbstractShape {
 public:
  virtual ~AbstractShape() = default;
  virtual std::unique_ptr<AbstractShape> clone() const = 0;
};

// This CRTP class implements clone() for Derived
template <typename Derived>
class Shape : public AbstractShape {
 public:
  std::unique_ptr<AbstractShape> clone() const override {
    return std::make_unique<Derived>(static_cast<Derived const&>(*this));
  }

 protected:
  // We make clear Shape class needs to be inherited
  Shape() = default;
  Shape(const Shape&) = default;
  Shape(Shape&&) = default;
};

class Square : public Shape<Square> {};

在 main() 函数中,以下编译

Square sq1;
std::unique_ptr<AbstractShape> sq2 = sq1.clone();
dynamic_cast<Square*>(sq2.get());

但是下面没有

Square sq1;
std::unique_ptr<AbstractShape> sq2 = sq1.clone();
std::dynamic_pointer_cast<Square>(sq2.get());

编译器报错

error: no matching function for call to ‘dynamic_pointer_cast<Square>(std::unique_ptr<AbstractShape>::pointer)’
   std::dynamic_pointer_cast<Square>(sq2.get());
                                              ^
In file included from /usr/include/c++/7/bits/shared_ptr.h:52:0,
                 from /usr/include/c++/7/memory:81,
                 from /home/mario/dev/bayesmix/test/crtp_aux.h:1,
                 from /home/mario/dev/bayesmix/test/crtp.cc:2:
/usr/include/c++/7/bits/shared_ptr_base.h:1571:5: note: candidate: template<class _Tp, class _Tp1, __gnu_cxx::_Lock_policy _Lp> std::__shared_ptr<_Tp1, _Lp> std::dynamic_pointer_cast(const std::__shared_ptr<_Tp2, _Lp>&)
     dynamic_pointer_cast(const __shared_ptr<_Tp1, _Lp>& __r) noexcept
     ^~~~~~~~~~~~~~~~~~~~
/usr/include/c++/7/bits/shared_ptr_base.h:1571:5: note:   template argument deduction/substitution failed:
/home/mario/dev/bayesmix/test/crtp.cc:37:46: note:   mismatched types ‘const std::__shared_ptr<_Tp2, _Lp>’ and ‘std::unique_ptr<AbstractShape>::pointer {aka AbstractShape*}’
   std::dynamic_pointer_cast<Square>(sq2.get());

基本上是说模板推演失败了。但是,Square 不是模板化的,也不是 AbstractShape.

std::shared_ptr<AbstractShape> sq2 = sq1.clone();
auto sq3 = std::dynamic_pointer_cast<Square>(sq2);

动态指针转换转换共享指针。失败的模板推导是转换函数的推导。

您只能传递 shared_ptr 作为 dynamic_pointer_cast 的参数。但是你传递了一个原始指针。所以我猜你有几个选择。

  1. 只用第一种方法(如果你不打算把它变成shared_ptr
  2. sq2转换为shared_ptr并传递(不带.get()