Horizon
Loading...
Searching...
No Matches
any.hpp
Go to the documentation of this file.
1
2// 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
26
28
29#include <range/v3/detail/prologue.hpp>
30
31RANGES_DIAGNOSTIC_PUSH
32RANGES_DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS
33
34namespace 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
230RANGES_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
Tiny meta-programming library.
Definition any.hpp:65
friend meta::if_c< std::is_reference< T >()||(bool) copyable< T >, T > any_cast(any &)
Definition any.hpp:184
Definition any.hpp:37