All Classes Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
any.hpp
1 // The MIT License (MIT)
2 
3 // Copyright (c) 2012-2014 Danny Y., Rapptz
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy of
6 // this software and associated documentation files (the "Software"), to deal in
7 // the Software without restriction, including without limitation the rights to
8 // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 // the Software, and to permit persons to whom the Software is furnished to do so,
10 // subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 
22 #ifndef GEARS_UTILITY_ANY_HPP
23 #define GEARS_UTILITY_ANY_HPP
24 
25 #include <type_traits>
26 #include <utility>
27 #include <typeinfo>
28 #include <memory>
29 
30 namespace gears {
31 namespace utility {
32 namespace detail {
33 struct bad_any_cast : public std::bad_cast {
34  virtual const char* what() const noexcept {
35  return "bad_any_cast";
36  }
37 };
38 } // detail
39 
82 class any {
83 private:
84  template<typename T>
85  using Decayed = typename std::decay<T>::type;
86 
87  struct base {
88  virtual ~base() {}
89  virtual std::unique_ptr<base> clone() const = 0;
90  };
91 
92  std::unique_ptr<base> obj;
93 
94  template<typename T>
95  struct object : base {
96  static_assert(std::is_copy_constructible<Decayed<T>>(), "Concept violation: T is not CopyConstructible");
97  template<typename U>
98  object(U&& v): value(std::forward<U>(v)) {}
99  T value;
100 
101  std::unique_ptr<base> clone() const {
102  return std::unique_ptr<base>(new object<T>(value));
103  }
104  };
105 
106  std::unique_ptr<base> clone() const {
107  return obj ? obj->clone() : nullptr;
108  }
109 public:
115  any() noexcept = default;
116 
127  template<typename T>
128  any(T&& actual) noexcept: obj(new(std::nothrow) object<Decayed<T>>(std::forward<T>(actual))) {}
129 
133  any(const any& other): obj(other.clone()) {}
134 
138  any(any&& other): obj(std::move(other.obj)) {}
139 
143  any& operator=(const any& other) {
144  if(obj == other.obj)
145  return *this;
146 
147  obj = other.clone();
148  return *this;
149  }
150 
154  any& operator=(any&& other) {
155  if(obj == other.obj)
156  return *this;
157 
158  obj.swap(other.obj);
159  return *this;
160  }
161 
168  explicit operator bool() const {
169  return static_cast<bool>(obj);
170  }
171 
183  template<typename T>
184  bool is() const {
185  auto ptr = dynamic_cast<object<Decayed<T>>*>(obj.get());
186  return ptr;
187  }
188 
190 
199  template<typename T>
200  const Decayed<T>& as() const {
201  auto ptr = dynamic_cast<object<Decayed<T>>*>(obj.get());
202  if(!ptr)
203  throw detail::bad_any_cast();
204  return ptr->value;
205  }
206 
207  template<typename T>
208  Decayed<T>& as() {
209  auto ptr = dynamic_cast<object<Decayed<T>>*>(obj.get());
210  if(!ptr)
211  throw detail::bad_any_cast();
212  return ptr->value;
213  }
215 };
216 
227 template<typename T>
228 inline auto any_cast(const any& object) -> decltype(object.as<T>()) {
229  return object.as<T>();
230 }
231 } // utility
232 } // gears
233 
234 #endif // GEARS_UTILITY_ANY_HPP