Reputation: 519
I'm considering the basic example of CRTP in Wikipedia
#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> {};
In a main() function, the following compiles
Square sq1;
std::unique_ptr<AbstractShape> sq2 = sq1.clone();
dynamic_cast<Square*>(sq2.get());
But the following does not
Square sq1;
std::unique_ptr<AbstractShape> sq2 = sq1.clone();
std::dynamic_pointer_cast<Square>(sq2.get());
and the compiler gives the error
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());
Basically saying that template deduction failed. However, Square
is not templated nor AbstractShape
.
Upvotes: 1
Views: 390
Reputation: 2152
You can only pass an shared_ptr
as the argument for dynamic_pointer_cast
. However you passed a raw pointer. So I guess you have a couple of options.
shared_ptr
)sq2
to shared_ptr
and pass it (without .get()
)Upvotes: 2
Reputation: 275740
std::shared_ptr<AbstractShape> sq2 = sq1.clone();
auto sq3 = std::dynamic_pointer_cast<Square>(sq2);
dynamic pointer cast converts shared ptrs. The template deduction that is failing is that of the cast function.
Upvotes: 4