neoGFX
Cross-platform C++ app/game engine
Loading...
Searching...
No Matches
any.hpp
Go to the documentation of this file.
1// any.hpp
2/*
3 * Copyright (c) 2007 Leigh Johnston.
4 *
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are
9 * met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * * Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 *
18 * * Neither the name of Leigh Johnston nor the names of any
19 * other contributors to this software may be used to endorse or
20 * promote products derived from this software without specific prior
21 * written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
24 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
25 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
28 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
29 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
30 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
31 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
32 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*/
35
36#pragma once
37
38#include <neolib/neolib.hpp>
39#include <any>
40#include <stdexcept>
41#include <typeinfo>
42
43#include <neolib/core/i_any.hpp>
45
46namespace neolib
47{
48 // todo: casts in this implementation of a polymorphic any mean this is not yet a solved problem (for passing across plugin boundaries)
49
50 template <typename T>
51 struct is_variant { static constexpr bool value = false; };
52 template <typename... Types>
53 struct is_variant<variant<Types...>> { static constexpr bool value = true; };
54 template <typename T>
56
57 class any : public i_any, private std::any
58 {
59 private:
60 template<class T>
61 friend T any_cast(const any& operand);
62 template<class T>
63 friend T any_cast(any& operand);
64 template<class T>
65 friend T any_cast(any&& operand);
66 template<class T>
67 friend const T* any_cast(const any* operand) noexcept;
68 template<class T>
69 friend T* any_cast(any* operand) noexcept;
70 template<class T>
71 friend T unsafe_any_cast(const any& operand) noexcept;
72 template<class T>
73 friend T unsafe_any_cast(any& operand) noexcept;
74 public:
75 any() :
76 cptr{ nullptr },
77 ptr{ nullptr }
78 {
79 }
80 any(const i_any& aOther) :
81 any{ static_cast<const any&>(aOther) } // todo - is it doable?
82 {
83 }
84 any(i_any&& aOther) :
85 any{ static_cast<any&>(aOther) } // todo - is it doable?
86 {
87 }
88 any(const any& aOther) :
89 std::any{ aOther.as_std_any() },
90 cptr{ aOther.cptr },
91 ptr{ aOther.ptr }
92 {
93 }
94 any(any&& aOther) :
95 std::any{ std::move(aOther.as_std_any()) },
96 cptr{ aOther.cptr },
97 ptr{ aOther.ptr }
98 {
99 aOther.cptr = nullptr;
100 aOther.ptr = nullptr;
101 }
102 template <typename ValueType>
103 any(ValueType&& aValue, std::enable_if_t<!is_variant_v<std::decay_t<ValueType>>, sfinae> = {}) :
104 std::any{ std::decay_t<ValueType>{aValue} },
105 cptr{ &any::do_cptr<std::decay_t<ValueType>> },
106 ptr{ &any::do_ptr<std::decay_t<ValueType>> }
107 {
108 }
109 template <typename ValueType>
110 explicit any(ValueType&& aVariant, std::enable_if_t<is_variant_v<std::decay_t<ValueType>>, sfinae> = {}) :
111 std::any{ std::decay_t<decltype(aVariant)>{aVariant} },
112 cptr{ &any::do_cptr<std::decay_t<decltype(aVariant)>> },
113 ptr{ &any::do_ptr<std::decay_t<decltype(aVariant)>> }
114 {
115 }
116 public:
117 any& operator=(const i_any& aRhs)
118 {
119 // todo - is it doable?
120 return *this = static_cast<const any&>(aRhs);
121 }
123 {
124 // todo - is it doable?
125 return *this = static_cast<any&>(aRhs);
126 }
127 any& operator=(const any& aRhs)
128 {
129 std::any::operator=(aRhs.as_std_any());
130 cptr = aRhs.cptr;
131 ptr = aRhs.ptr;
132 return *this;
133 }
135 {
136 std::any::operator=(std::move(aRhs.as_std_any()));
137 cptr = aRhs.cptr;
138 ptr = aRhs.ptr;
139 aRhs.cptr = nullptr;
140 aRhs.ptr = nullptr;
141 return *this;
142 }
143 template<typename ValueType>
144 any& operator=(ValueType&& aRhs)
145 {
146 std::any::operator=(std::decay_t<ValueType>{aRhs});
147 cptr = &any::do_cptr<std::decay_t<ValueType>>;
148 ptr = &any::do_ptr<std::decay_t<ValueType>>;
149 return *this;
150 }
151 public:
152 template<class ValueType, class... Args>
153 std::decay_t<ValueType>& emplace(Args&&... args)
154 {
155 auto& result = std::any::emplace<ValueType>(std::forward<Args...>(args...));
156 cptr = &any::do_cptr<std::decay_t<ValueType>>;
157 ptr = &any::do_ptr<std::decay_t<ValueType>>;
158 return result;
159 }
160 template<class ValueType, class U, class... Args>
161 std::decay_t<ValueType>& emplace(std::initializer_list<U> il, Args&&... args)
162 {
163 auto& result = std::any::emplace<ValueType>(il, std::forward<Args...>(args...));
164 cptr = &any::do_cptr<std::decay_t<ValueType>>;
165 ptr = &any::do_ptr<std::decay_t<ValueType>>;
166 return result;
167 }
168 void reset() override
169 {
170 std::any::reset();
171 cptr = nullptr;
172 ptr = nullptr;
173 }
174 void swap(any& aOther)
175 {
176 std::any::swap(aOther.as_std_any());
177 std::swap(cptr, aOther.cptr);
178 std::swap(ptr, aOther.ptr);
179 }
180 public:
181 bool has_value() const override
182 {
183 return std::any::has_value();
184 }
185 std::type_info const& type() const override
186 {
187 return std::any::type();
188 }
189 public:
190 bool operator==(const i_any& aOther) const override
191 {
192 return *this == static_cast<const any&>(aOther);
193 }
194 bool operator!=(const i_any& aOther) const override
195 {
196 return *this != static_cast<const any&>(aOther);
197 }
198 bool operator<(const i_any& aOther) const override
199 {
200 return *this < static_cast<const any&>(aOther);
201 }
202 bool operator==(const any& aOther) const
203 {
204 if (cptr != nullptr && aOther.cptr != nullptr)
205 return cptr(*this) == aOther.cptr(aOther);
206 else
207 return cptr == aOther.cptr;
208 }
209 bool operator!=(const any& aOther) const
210 {
211 if (cptr != nullptr && aOther.cptr != nullptr)
212 return cptr(*this) != aOther.cptr(aOther);
213 else
214 return cptr != aOther.cptr;
215 }
216 bool operator<(const any& aOther) const
217 {
218 if (cptr != nullptr && aOther.cptr != nullptr)
219 return cptr(*this) < aOther.cptr(aOther);
220 else
221 return cptr < aOther.cptr;
222 }
223 private:
224 const std::any& as_std_any() const override
225 {
226 return *this;
227 }
228 std::any& as_std_any() override
229 {
230 return *this;
231 }
232 const void* unsafe_ptr() const override
233 {
234 if (cptr != nullptr)
235 return cptr(*this);
236 else
237 return nullptr;
238 }
239 void* unsafe_ptr() override
240 {
241 if (cptr != nullptr)
242 return ptr(*this);
243 else
244 return nullptr;
245 }
246 template <typename T>
247 static const void* do_cptr(const any& aArg)
248 {
249 return &std::any_cast<const T&>(aArg.as_std_any());
250 }
251 template <typename T>
252 static void* do_ptr(any& aArg)
253 {
254 return &std::any_cast<T&>(aArg.as_std_any());
255 }
256 private:
257 const void*(*cptr)(const any&);
258 void*(*ptr)(any&);
259 };
260
261 inline void swap(any& aLhs, any& aRhs)
262 {
263 aLhs.swap(aRhs);
264 }
265
266 template<class T>
267 inline T any_cast(const any& operand)
268 {
269 return std::any_cast<T>(operand.as_std_any());
270 }
271 template<class T>
272 inline T any_cast(any& operand)
273 {
274 return std::any_cast<T>(operand.as_std_any());
275 }
276 template<class T>
277 inline T any_cast(any&& operand)
278 {
279 return std::any_cast<T>(std::move(operand.as_std_any()));
280 }
281 template<class T>
282 inline const T* any_cast(const any* operand) noexcept
283 {
284 return std::any_cast<const T*>(&operand->as_std_any());
285 }
286 template<class T>
287 inline T* any_cast(any* operand) noexcept
288 {
289 return std::any_cast<T*>(&operand->as_std_any());
290 }
291 template<class T>
292 inline T unsafe_any_cast(const any& operand) noexcept
293 {
294 return *static_cast<const std::decay_t<T>*>(operand.unsafe_ptr());
295 }
296 template<class T>
297 inline T unsafe_any_cast(any& operand) noexcept
298 {
299 return *static_cast<std::decay_t<T>*>(operand.unsafe_ptr());
300 }
301}
void swap(any &aOther)
Definition any.hpp:174
std::decay_t< ValueType > & emplace(std::initializer_list< U > il, Args &&... args)
Definition any.hpp:161
bool operator==(const i_any &aOther) const override
Definition any.hpp:190
any & operator=(any &&aRhs)
Definition any.hpp:134
friend T unsafe_any_cast(const any &operand) noexcept
Definition any.hpp:292
bool operator!=(const i_any &aOther) const override
Definition any.hpp:194
any & operator=(ValueType &&aRhs)
Definition any.hpp:144
any & operator=(i_any &&aRhs)
Definition any.hpp:122
any(const any &aOther)
Definition any.hpp:88
any(ValueType &&aValue, std::enable_if_t<!is_variant_v< std::decay_t< ValueType > >, sfinae >={})
Definition any.hpp:103
any(i_any &&aOther)
Definition any.hpp:84
friend T any_cast(const any &operand)
Definition any.hpp:267
void reset() override
Definition any.hpp:168
bool operator==(const any &aOther) const
Definition any.hpp:202
std::type_info const & type() const override
Definition any.hpp:185
any(ValueType &&aVariant, std::enable_if_t< is_variant_v< std::decay_t< ValueType > >, sfinae >={})
Definition any.hpp:110
any & operator=(const any &aRhs)
Definition any.hpp:127
bool operator<(const i_any &aOther) const override
Definition any.hpp:198
bool operator<(const any &aOther) const
Definition any.hpp:216
any(any &&aOther)
Definition any.hpp:94
any & operator=(const i_any &aRhs)
Definition any.hpp:117
std::decay_t< ValueType > & emplace(Args &&... args)
Definition any.hpp:153
bool operator!=(const any &aOther) const
Definition any.hpp:209
bool has_value() const override
Definition any.hpp:181
any(const i_any &aOther)
Definition any.hpp:80
constexpr bool is_variant_v
Definition any.hpp:55
T unsafe_any_cast(const any &operand) noexcept
Definition any.hpp:292
T any_cast(const any &operand)
Definition any.hpp:267
Definition plf_hive.h:79
void swap(plf::hive< element_type, allocator_type > &a, plf::hive< element_type, allocator_type > &b) noexcept(std::allocator_traits< allocator_type >::propagate_on_container_swap::value||std::allocator_traits< allocator_type >::is_always_equal::value)
Definition plf_hive.h:4776
static constexpr bool value
Definition any.hpp:51