boost_any.hpp
1 // Author: Mario S. Könz <mskoenz@gmx.net>
2 // Date: 15.01.2015 18:07:11 CET
3 // File: boost_any.hpp
4 
5 #ifndef BOOST_ANY_HEADER
6 #define BOOST_ANY_HEADER
7 
8 #include <algorithm>
9 #include <typeinfo>
10 #include <type_traits>
11 
13 namespace boost {
14  class any {
15  public: // structors
16  any(): content(0) {}
17 
18  template<typename ValueType>
19  any(const ValueType & value): content(new holder<ValueType>(value)) {}
20 
21  any(const any & other): content(other.content ? other.content->clone() : 0) {}
22 
23  // Move constructor
24  any(any&& other): content(other.content) {
25  other.content = 0;
26  }
27 
28  // Perfect forwarding of ValueType
29  template<typename ValueType>
30  any(ValueType&& value, typename std::enable_if<!std::is_same<any&, ValueType>::value >::type* = 0)
31  : content(new holder< typename std::remove_reference<ValueType>::type >(static_cast<ValueType&&>(value))) {}
32 
33  ~any() {
34  delete content;
35  }
36 
37  public: // modifiers
38 
39  any & swap(any & rhs) {
40  std::swap(content, rhs.content);
41  return *this;
42  }
43 
44  any & operator=(const any& rhs) {
45  any(rhs).swap(*this);
46  return *this;
47  }
48 
49  // move assignement
50  any & operator=(any&& rhs) {
51  rhs.swap(*this);
52  any().swap(rhs);
53  return *this;
54  }
55 
56  // Perfect forwarding of ValueType
57  template <class ValueType>
58  any & operator=(ValueType&& rhs) {
59  any(static_cast<ValueType&&>(rhs)).swap(*this);
60  return *this;
61  }
62 
63  public: // queries
64 
65  bool empty() const {
66  return !content;
67  }
68 
69  const std::type_info & type() const {
70  return content ? content->type() : typeid(void);
71  }
72 
73  private: // types
74  class placeholder {
75  public: // structors
76  virtual ~placeholder() {}
77  public: // queries
78  virtual const std::type_info & type() const = 0;
79  virtual placeholder * clone() const = 0;
80  };
81 
82  template<typename ValueType>
83  class holder : public placeholder {
84  public: // structors
85  holder(const ValueType & value): held(value) {}
86  holder(ValueType&& value): held(static_cast< ValueType&& >(value)) {}
87  public: // queries
88  virtual const std::type_info & type() const {
89  return typeid(ValueType);
90  }
91  virtual placeholder * clone() const {
92  return new holder(held);
93  }
94  public: // representation
95  ValueType held;
96 
97  private: // intentionally left unimplemented
98  holder & operator=(const holder &);
99  };
100 
101  private: // representation
102 
103  template<typename ValueType>
104  friend ValueType * any_cast(any *);
105 
106  template<typename ValueType>
107  friend ValueType * unsafe_any_cast(any *);
108 
109  placeholder * content;
110  };
111 
112  inline void swap(any & lhs, any & rhs) {
113  lhs.swap(rhs);
114  }
115 
116  class bad_any_cast : public std::bad_cast {
117  public:
118  virtual const char * what() const noexcept {
119  return "boost::bad_any_cast: "
120  "failed conversion using boost::any_cast";
121  }
122  };
123 
124  template<typename ValueType>
125  ValueType * any_cast(any * operand) {
126  return operand && operand->type() == typeid(ValueType) ? &static_cast<any::holder<ValueType> *>(operand->content)->held: 0;
127  }
128 
129  template<typename ValueType>
130  inline const ValueType * any_cast(const any * operand) {
131  return any_cast<ValueType>(const_cast<any *>(operand));
132  }
133 
134  template<typename ValueType>
135  ValueType any_cast(any & operand) {
136  typedef typename std::remove_reference<ValueType>::type nonref;
137 
138  nonref * result = any_cast<nonref>(&operand);
139  if(!result)
140  throw(bad_any_cast());
141  return *result;
142  }
143 
144  template<typename ValueType>
145  inline ValueType any_cast(const any & operand) {
146  typedef typename std::remove_reference<ValueType>::type nonref;
147  return any_cast<const nonref &>(const_cast<any &>(operand));
148  }
149 
150  // Note: The "unsafe" versions of any_cast are not part of the
151  // public interface and may be removed at any time. They are
152  // required where we know what type is stored in the any and can't
153  // use typeid() comparison, e.g., when our types may travel across
154  // different shared libraries.
155  template<typename ValueType>
156  inline ValueType * unsafe_any_cast(any * operand) {
157  return &static_cast<any::holder<ValueType> *>(operand->content)->held;
158  }
159 
160  template<typename ValueType>
161  inline const ValueType * unsafe_any_cast(const any * operand) {
162  return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
163  }
164 }
166 
167 #endif //BOOST_ANY_HEADER