I have created a template class derived from shared_ptr<const T>
that enables a holder of the shared pointer to modify the pointed instance by cloning the instance and reseting the shared_pointer. (T
can be a clonable class or a class that have a copy constructor whence the weird double definition of the modify method)
shared_ptr<Base>
can be implicitly constructed/copied by a instance of class shared_ptr<Derived>
. But my class cannot.
How can I make that possible? I suppose I need to create a templated constructor that accepts argument of type const_shared_ptr<D>
where D
is a type derived from the template type C
. I don't know how to write that. I guess it is possible as shared_ptr
can do it.
template <typename T, typename = int>
struct HasPolymorphicClonage : std::false_type { };
template <typename T>
struct HasPolymorphicClonage <T, decltype(&T::clone, 0)> : std::true_type { };
template<typename C>
class shared_const_ptr : public std::shared_ptr<const C>
{
public :
shared_const_ptr(const C * c) : std::shared_ptr<const C>(c) {}
shared_const_ptr() =default;
// définition de la méthode modify selon que T propose ou non une méthode clone
template<typename T1 = C>
typename std::enable_if_t<HasPolymorphicClonage<T1>::value,C&> modify()
{
C * remplacant = (*this)->clone();
this->std::shared_ptr<const C>::reset(remplacant);
return *remplacant;
}
template<typename T1 = C>
typename std::enable_if_t<!HasPolymorphicClonage<T1>::value,C&> modify()
{
C * remplacant = new C(**this); // on utilise le constructeur par recopie
this->std::shared_ptr<const C>::reset(remplacant);
return *remplacant;
}
};
Adding a templated constructor accepting a std::shared_ptr<T>
should work:
template<typename C>
class shared_const_ptr : public std::shared_ptr<const C>
{
public :
// ...
template <typename T>
shared_const_ptr(std::shared_ptr<const T> const& other) : std::shared_ptr<const C>(other) {}
};
struct Base {};
struct Derived : Base {};
int main()
{
shared_const_ptr<Base> b;
shared_const_ptr d(new Derived{});
b = d;
}
https://godbolt.org/z/n45PKE9ff
When constructing b
fromd
, argument conversion will convert d
to a std::shared_ptr<const Derived>
. The constructor is viable because std::shared_ptr<const Derived>
is convertible to std::shared_ptr<const Base>
.