Advertisement
Radfler

std::any

Apr 9th, 2016 (edited)
126
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.38 KB | None | 0 0
  1. #include <exception>
  2. #include <type_traits>
  3. #include <typeinfo>
  4. #include <utility>
  5.  
  6. namespace details {
  7.  
  8.     struct any_value_base {
  9.  
  10.         virtual const type_info& type() const = 0;
  11.         virtual any_value_base* clone() const = 0;
  12.         virtual ~any_value_base() = default;
  13.  
  14.     };
  15.  
  16.     template<typename ValueType>
  17.     struct any_value : any_value_base {
  18.  
  19.         any_value(const ValueType& value) : value(value) { }
  20.  
  21.         ValueType value;
  22.  
  23.         const type_info& type() const override {
  24.             return typeid(ValueType);
  25.         }
  26.  
  27.         any_value_base* clone() const override {
  28.             return new any_value(value);
  29.         }
  30.  
  31.     };
  32.  
  33. }
  34.  
  35. class bad_any_cast : std::exception {
  36.  
  37.     virtual const char* what() const noexcept override {
  38.         return "invalid any_cast";
  39.     }
  40.  
  41. };
  42.  
  43. class any {
  44.  
  45. public:
  46.  
  47.     any() noexcept : value(nullptr) { }
  48.  
  49.     any(const any& other) {
  50.    
  51.         if(other.value != nullptr) {
  52.             value = other.value->clone();
  53.         } else {
  54.             value = nullptr;
  55.         }
  56.  
  57.     }
  58.  
  59.     any(any&& other) noexcept : value(other.value) {
  60.         other.value = nullptr;
  61.     }
  62.  
  63.     template<typename ValueType, typename = std::enable_if_t<!std::is_same<std::decay_t<ValueType>, any>::value>>
  64.     any(ValueType&& value) : value(new details::any_value<std::decay_t<ValueType>>(std::forward<ValueType>(value))) {
  65.  
  66.         static_assert(std::is_copy_constructible<std::decay_t<ValueType>>::value,
  67.                       "std::decay_t<ValueType> does not satisfy CopyConstructible requirements");
  68.  
  69.     }
  70.  
  71.     ~any() {
  72.         clear();
  73.     }
  74.  
  75.     any& operator=(const any& other) {
  76.         if(this != &other) {
  77.             any(other).swap(*this);
  78.         }
  79.  
  80.         return *this;
  81.     }
  82.  
  83.     any& operator=(any&& other) noexcept {
  84.         if(this != &other) {
  85.             any(std::move(other)).swap(*this);
  86.         }
  87.  
  88.         return *this;
  89.     }
  90.    
  91.     template<typename ValueType>
  92.     std::enable_if_t<!std::is_same<std::decay_t<ValueType>, any>::value, any&> operator=(ValueType&& value) {
  93.  
  94.         static_assert(std::is_copy_constructible<std::decay_t<ValueType>>::value,
  95.                       "std::decay_t<ValueType> does not satisfy CopyConstructible requirements");
  96.  
  97.         any(std::forward<ValueType>(value)).swap(*this);
  98.         return *this;
  99.  
  100.     }
  101.  
  102.     void clear() noexcept {
  103.         delete value;
  104.     }
  105.  
  106.     void swap(any& other) noexcept {
  107.         std::swap(value, other.value);
  108.     }
  109.  
  110.     bool empty() const noexcept {
  111.         return value == nullptr;
  112.     }
  113.  
  114.     const std::type_info& type() const noexcept {
  115.         if(empty()) {
  116.             return typeid(void);
  117.         }
  118.         return value->type();
  119.     }
  120.  
  121. private:
  122.  
  123.     details::any_value_base* value;
  124.  
  125.     template<class ValueType>
  126.     friend const ValueType* any_cast(const any* operand) noexcept;
  127.  
  128.     template<class ValueType>
  129.     friend ValueType* any_cast(any* operand) noexcept;
  130.  
  131. };
  132.  
  133. void swap(any& lhs, any& rhs) noexcept {
  134.     lhs.swap(rhs);
  135. }
  136.  
  137. template<class ValueType>
  138. ValueType any_cast(const any& operand) {
  139.  
  140.     static_assert(std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value,
  141.                   "ValueType must be reference type or copy constructible type");
  142.  
  143.     if(operand.type() != typeid(std::remove_reference_t<ValueType>)) {
  144.         throw bad_any_cast();
  145.     }
  146.  
  147.     return *any_cast<std::add_const_t<std::remove_reference_t<ValueType>>>(&operand);
  148. }
  149.  
  150. template<class ValueType>
  151. ValueType any_cast(any& operand) {
  152.  
  153.     static_assert(std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value,
  154.                   "ValueType must be reference type or copy constructible type");
  155.  
  156.     if(operand.type() != typeid(std::remove_reference_t<ValueType>)) {
  157.         throw bad_any_cast();
  158.     }
  159.  
  160.     return *any_cast<std::remove_reference_t<ValueType>>(&operand);
  161.  
  162. }
  163.  
  164. template<class ValueType>
  165. ValueType any_cast(any&& operand) {
  166.  
  167.     static_assert(std::is_reference<ValueType>::value || std::is_copy_constructible<ValueType>::value,
  168.                   "ValueType must be reference type or copy constructible type");
  169.  
  170.     if(operand.type() != typeid(std::remove_reference_t<ValueType>)) {
  171.         throw bad_any_cast();
  172.     }
  173.  
  174.     return *any_cast<std::remove_reference_t<ValueType>>(&operand);
  175.  
  176. }
  177.  
  178. template<class ValueType>
  179. const ValueType* any_cast(const any* operand) noexcept {
  180.    
  181.     if(operand != nullptr && operand->type() == typeid(ValueType)) {
  182.         return &static_cast<details::any_value<ValueType>*>(operand->value)->value;
  183.     }
  184.  
  185.     return nullptr;
  186.  
  187. }
  188.  
  189. template<class ValueType>
  190. ValueType* any_cast(any* operand) noexcept {
  191.  
  192.     if(operand != nullptr && operand->type() == typeid(ValueType)) {
  193.         return &static_cast<details::any_value<ValueType>*>(operand->value)->value;
  194.     }
  195.  
  196.     return nullptr;
  197.  
  198. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement