英文:
How to write constructors for implicit conversions from instances of a templated class C<Derived> to instances of C<Base>
问题
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 resetting the shared_pointer. (T
can be a clonable class or a class that has a copy constructor, hence the weird double definition of the modify method)
shared_ptr<Base>
can be implicitly constructed/copied by an 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 an 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;
// Definition of the modify method depending on whether T offers a clone method or not
template<typename T1 = C>
typename std::enable_if_t<HasPolymorphicClonage<T1>::value, C&> modify()
{
C * replacement = (*this)->clone();
this->std::shared_ptr<const C>::reset(replacement);
return *replacement;
}
template<typename T1 = C>
typename std::enable_if_t<!HasPolymorphicClonage<T1>::value, C&> modify()
{
C * replacement = new C(**this); // Using the copy constructor
this->std::shared_ptr<const C>::reset(replacement);
return *replacement;
}
};
(Note: I have translated the provided code into English, but I have not modified the code itself.)
英文:
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;
}
};
答案1
得分: 1
添加一个接受 std::shared_ptr<T>
的模板构造函数应该可以工作:
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;
}
当从 d
构造 b
时,参数转换会将 d
转换为 std::shared_ptr<const Derived>
。这个构造函数是可行的,因为 std::shared_ptr<const Derived>
可以转换为 std::shared_ptr<const Base>
。
英文:
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>
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论