How to write constructors for implicit conversions from instances of a templated class C<Derived> to instances of C<Base>

huangapple go评论95阅读模式
英文:

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.

  1. template <typename T, typename = int>
  2. struct HasPolymorphicClonage : std::false_type { };
  3. template <typename T>
  4. struct HasPolymorphicClonage <T, decltype(&T::clone, 0)> : std::true_type { };
  5. template<typename C>
  6. class shared_const_ptr : public std::shared_ptr<const C>
  7. {
  8. public :
  9. shared_const_ptr(const C * c) : std::shared_ptr<const C>(c) {}
  10. shared_const_ptr() = default;
  11. // Definition of the modify method depending on whether T offers a clone method or not
  12. template<typename T1 = C>
  13. typename std::enable_if_t<HasPolymorphicClonage<T1>::value, C&> modify()
  14. {
  15. C * replacement = (*this)->clone();
  16. this->std::shared_ptr<const C>::reset(replacement);
  17. return *replacement;
  18. }
  19. template<typename T1 = C>
  20. typename std::enable_if_t<!HasPolymorphicClonage<T1>::value, C&> modify()
  21. {
  22. C * replacement = new C(**this); // Using the copy constructor
  23. this->std::shared_ptr<const C>::reset(replacement);
  24. return *replacement;
  25. }
  26. };

(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&lt;const T&gt; 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&lt;Base&gt; can be implicitly constructed/copied by a instance of class shared_ptr&lt;Derived&gt;. 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&lt;D&gt; 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.

  1. template &lt;typename T, typename = int&gt;
  2. struct HasPolymorphicClonage : std::false_type { };
  3. template &lt;typename T&gt;
  4. struct HasPolymorphicClonage &lt;T, decltype(&amp;T::clone, 0)&gt; : std::true_type { };
  5. template&lt;typename C&gt;
  6. class shared_const_ptr : public std::shared_ptr&lt;const C&gt;
  7. {
  8. public :
  9. shared_const_ptr(const C * c) : std::shared_ptr&lt;const C&gt;(c) {}
  10. shared_const_ptr() =default;
  11. // d&#233;finition de la m&#233;thode modify selon que T propose ou non une m&#233;thode clone
  12. template&lt;typename T1 = C&gt;
  13. typename std::enable_if_t&lt;HasPolymorphicClonage&lt;T1&gt;::value,C&amp;&gt; modify()
  14. {
  15. C * remplacant = (*this)-&gt;clone();
  16. this-&gt;std::shared_ptr&lt;const C&gt;::reset(remplacant);
  17. return *remplacant;
  18. }
  19. template&lt;typename T1 = C&gt;
  20. typename std::enable_if_t&lt;!HasPolymorphicClonage&lt;T1&gt;::value,C&amp;&gt; modify()
  21. {
  22. C * remplacant = new C(**this); // on utilise le constructeur par recopie
  23. this-&gt;std::shared_ptr&lt;const C&gt;::reset(remplacant);
  24. return *remplacant;
  25. }
  26. };

答案1

得分: 1

添加一个接受 std::shared_ptr&lt;T&gt; 的模板构造函数应该可以工作:

  1. template&lt;typename C&gt;
  2. class shared_const_ptr : public std::shared_ptr&lt;const C&gt;
  3. {
  4. public:
  5. // ...
  6. template &lt;typename T&gt;
  7. shared_const_ptr(std::shared_ptr&lt;const T&gt; const&amp; other) : std::shared_ptr&lt;const C&gt;(other) {}
  8. };
  9. struct Base {};
  10. struct Derived : Base {};
  11. int main()
  12. {
  13. shared_const_ptr&lt;Base&gt; b;
  14. shared_const_ptr d(new Derived{});
  15. b = d;
  16. }

当从 d 构造 b 时,参数转换会将 d 转换为 std::shared_ptr&lt;const Derived&gt;。这个构造函数是可行的,因为 std::shared_ptr&lt;const Derived&gt; 可以转换为 std::shared_ptr&lt;const Base&gt;

英文:

Adding a templated constructor accepting a std::shared_ptr&lt;T&gt; should work:

  1. template&lt;typename C&gt;
  2. class shared_const_ptr : public std::shared_ptr&lt;const C&gt;
  3. {
  4. public :
  5. // ...
  6. template &lt;typename T&gt;
  7. shared_const_ptr(std::shared_ptr&lt;const T&gt; const&amp; other) : std::shared_ptr&lt;const C&gt;(other) {}
  8. };
  9. struct Base {};
  10. struct Derived : Base {};
  11. int main()
  12. {
  13. shared_const_ptr&lt;Base&gt; b;
  14. shared_const_ptr d(new Derived{});
  15. b = d;
  16. }

https://godbolt.org/z/n45PKE9ff

When constructing b fromd, argument conversion will convert d to a std::shared_ptr&lt;const Derived&gt;. The constructor is viable because std::shared_ptr&lt;const Derived&gt; is convertible to std::shared_ptr&lt;const Base&gt;.

huangapple
  • 本文由 发表于 2023年4月19日 18:56:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76053679.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定