fork download
  1. #include <memory>
  2. #include <type_traits>
  3. #include <iostream>
  4.  
  5. template<class BaseT>
  6. class polyval {
  7. public:
  8. template<class U>
  9. polyval(const U& val) {
  10. static_assert(std::is_same<BaseT, U>::value || std::is_base_of<BaseT, U>::value, "U must be BaseT or derived from BaseT.");
  11. val_ = std::unique_ptr<BaseT>(new U(val));
  12. }
  13.  
  14. template<class U>
  15. polyval(U&& val) {
  16. static_assert(std::is_same<BaseT, U>::value || std::is_base_of<BaseT, U>::value, "U must be BaseT or derived from BaseT.");
  17. val_ = std::unique_ptr<BaseT>(new U(std::move(val)));
  18. }
  19.  
  20. polyval(const polyval<BaseT>&) = delete;
  21. polyval(polyval<BaseT>&&) = delete;
  22.  
  23. polyval<BaseT>& operator=(const polyval<BaseT>&) = delete;
  24. polyval<BaseT>& operator=(const polyval<BaseT>&&) = delete;
  25.  
  26. template<class U = BaseT>
  27. U& get() {
  28. static_assert(std::is_same<BaseT, U>::value || std::is_base_of<BaseT, U>::value, "U must be BaseT or derived from BaseT.");
  29. return dynamic_cast<U&>(*val_);
  30. }
  31.  
  32. template<class U = BaseT>
  33. const U& get() const {
  34. static_assert(std::is_same<BaseT, U>::value || std::is_base_of<BaseT, U>::value, "U must be BaseT or derived from BaseT.");
  35. return dynamic_cast<U&>(*val_);
  36. }
  37.  
  38. private:
  39. std::unique_ptr<BaseT> val_;
  40.  
  41. friend void swap(polyval<BaseT>& a, polyval<BaseT>& b) {
  42. using std::swap;
  43. swap(a.val_, b.val_);
  44. }
  45. };
  46.  
  47. class B {
  48. public:
  49. virtual void foo() { std::cout << "B\n"; }
  50. };
  51.  
  52. class D1 : public B {
  53. public:
  54. virtual void foo() { std::cout << "D1\n"; }
  55. };
  56.  
  57. class D2 : public D1 {
  58. public:
  59. virtual void foo() { std::cout << "D2\n"; }
  60. };
  61.  
  62. class D3 : public D2 {
  63. public:
  64. virtual void foo() { std::cout << "cannot happen.\n"; }
  65. };
  66.  
  67. int main() {
  68. polyval<B> b((B()));
  69. polyval<B> d1((D1()));
  70. polyval<B> d2((D2()));
  71.  
  72. b.get().foo();
  73. d1.get<D1>().foo();
  74. d2.get().foo();
  75. d2.get<D3>().foo();
  76. }
Runtime error #stdin #stdout 0s 2960KB
stdin
Standard input is empty
stdout
B
D1
D2