Horizon
any.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2015-present
5 //
6 // Use, modification and distribution is subject to the
7 // Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at
9 // http://www.boost.org/LICENSE_1_0.txt)
10 //
11 // Project home: https://github.com/ericniebler/range-v3
12 //
13 
14 #ifndef RANGES_V3_UTILITY_ANY_HPP
15 #define RANGES_V3_UTILITY_ANY_HPP
16 
17 #include <memory>
18 #include <type_traits>
19 #include <typeinfo>
20 
21 #include <meta/meta.hpp>
22 
23 #include <concepts/concepts.hpp>
24 
25 #include <range/v3/range_fwd.hpp>
26 
28 
29 #include <range/v3/detail/prologue.hpp>
30 
31 RANGES_DIAGNOSTIC_PUSH
32 RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
33 
34 namespace ranges
35 {
36  struct bad_any_cast : std::bad_cast
37  {
38  virtual const char * what() const noexcept override
39  {
40  return "bad any_cast";
41  }
42  };
43 
44  struct RANGES_DEPRECATED(
45  "ranges::any will be going away in the not-too-distant future. "
46  "We suggest you use std::any or boost::any instead (or simply steal "
47  "this header and maintain it yourself).") any;
48 
49  template<typename T>
50  meta::if_c<std::is_reference<T>() || copyable<T>, T> any_cast(any &);
51 
52  template<typename T>
53  meta::if_c<std::is_reference<T>() || copyable<T>, T> any_cast(any const &);
54 
55  template<typename T>
56  meta::if_c<std::is_reference<T>() || copyable<T>, T> any_cast(any &&);
57 
58  template<typename T>
59  T * any_cast(any *) noexcept;
60 
61  template<typename T>
62  T const * any_cast(any const *) noexcept;
63 
64  struct any
65  {
66  private:
67  template<typename T>
68  friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(any &);
69 
70  template<typename T>
71  friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(
72  any const &);
73 
74  template<typename T>
75  friend meta::if_c<std::is_reference<T>() || (bool)copyable<T>, T> any_cast(
76  any &&);
77 
78  template<typename T>
79  friend T * any_cast(any *) noexcept;
80 
81  template<typename T>
82  friend T const * any_cast(any const *) noexcept;
83 
84  struct interface
85  {
86  virtual ~interface()
87  {}
88  virtual interface * clone() const = 0;
89  virtual std::type_info const & type() const noexcept = 0;
90  };
91 
92  template<typename T>
93  struct impl final : interface
94  {
95  private:
96  T obj;
97 
98  public:
99  impl() = default;
100  impl(T o)
101  : obj(std::move(o))
102  {}
103  T & get()
104  {
105  return obj;
106  }
107  T const & get() const
108  {
109  return obj;
110  }
111  impl * clone() const override
112  {
113  return new impl{obj};
114  }
115  std::type_info const & type() const noexcept override
116  {
117  return typeid(T);
118  }
119  };
120 
121  std::unique_ptr<interface> ptr_;
122 
123  public:
124  any() noexcept = default;
125  template(typename TRef, typename T = detail::decay_t<TRef>)(
126  requires copyable<T> AND (!same_as<T, any>)) //
127  any(TRef && t)
128  : ptr_(new impl<T>(static_cast<TRef &&>(t)))
129  {}
130  any(any &&) noexcept = default;
131  any(any const & that)
132  : ptr_{that.ptr_ ? that.ptr_->clone() : nullptr}
133  {}
134  any & operator=(any &&) noexcept = default;
135  any & operator=(any const & that)
136  {
137  ptr_.reset(that.ptr_ ? that.ptr_->clone() : nullptr);
138  return *this;
139  }
140  template(typename TRef, typename T = detail::decay_t<TRef>)(
141  requires copyable<T> AND (!same_as<T, any>)) //
142  any & operator=(TRef && t)
143  {
144  any{static_cast<TRef &&>(t)}.swap(*this);
145  return *this;
146  }
147  void clear() noexcept
148  {
149  ptr_.reset();
150  }
151  bool empty() const noexcept
152  {
153  return !ptr_;
154  }
155  std::type_info const & type() const noexcept
156  {
157  return ptr_ ? ptr_->type() : typeid(void);
158  }
159  void swap(any & that) noexcept
160  {
161  ptr_.swap(that.ptr_);
162  }
163 
164 #if !RANGES_BROKEN_CPO_LOOKUP
165  friend void swap(any & x, any & y) noexcept
166  {
167  x.swap(y);
168  }
169 #endif
170  };
171 
172 #if RANGES_BROKEN_CPO_LOOKUP
173  namespace _any_
174  {
175  inline void swap(any & x, any & y) noexcept
176  {
177  x.swap(y);
178  }
179  } // namespace _any_
180 #endif
181 
183  template<typename T>
184  meta::if_c<std::is_reference<T>() || copyable<T>, T> any_cast(any & x)
185  {
186  if(x.type() != typeid(detail::decay_t<T>))
187  throw bad_any_cast{};
188  return static_cast<any::impl<detail::decay_t<T>> *>(x.ptr_.get())->get();
189  }
190 
192  template<typename T>
193  meta::if_c<std::is_reference<T>() || copyable<T>, T> any_cast(any const & x)
194  {
195  if(x.type() != typeid(detail::decay_t<T>))
196  throw bad_any_cast{};
197  return static_cast<any::impl<detail::decay_t<T>> const *>(x.ptr_.get())->get();
198  }
199 
201  template<typename T>
202  meta::if_c<std::is_reference<T>() || copyable<T>, T> any_cast(any && x)
203  {
204  if(x.type() != typeid(detail::decay_t<T>))
205  throw bad_any_cast{};
206  return static_cast<any::impl<detail::decay_t<T>> *>(x.ptr_.get())->get();
207  }
208 
210  template<typename T>
211  T * any_cast(any * p) noexcept
212  {
213  if(p && p->ptr_)
214  if(any::impl<T> * q = dynamic_cast<any::impl<T> *>(p->ptr_.get()))
215  return &q->get();
216  return nullptr;
217  }
218 
220  template<typename T>
221  T const * any_cast(any const * p) noexcept
222  {
223  if(p && p->ptr_)
224  if(any::impl<T> const * q = dynamic_cast<any::impl<T> const *>(p->ptr_.get()))
225  return &q->get();
226  return nullptr;
227  }
228 } // namespace ranges
229 
230 RANGES_DIAGNOSTIC_POP
231 
232 #include <range/v3/detail/epilogue.hpp>
233 
234 #endif
meta::if_c< std::is_reference< T >)||copyable< T >, T > any_cast(any &)
Definition: any.hpp:184
template(typename ActionFn, typename Rng)(concept(invocable_action_closure_)(ActionFn
\concept invocable_action_closure_
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition: meta.hpp:2231
not_< empty< find< L, T > >> in
A Boolean integral constant wrapper around true if there is at least one occurrence of T in L.
Definition: meta.hpp:3081
Tiny meta-programming library.
Definition: any.hpp:65
Definition: any.hpp:37
Definition: pipeable.hpp:76