【发布时间】:2021-02-03 11:26:47
【问题描述】:
我正在考虑维基百科中 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::dynamic_pointer_cast转换智能指针:传递sq2而不是sq2.get()。编辑:我读得太快了,它也专门用于std::shared_ptr。见this question。 -
你为什么需要演员表?协变返回类型或简单的接口使用没有干净的方法吗?
标签: c++ templates polymorphism crtp