1 // The MIT License (MIT)
2 
3 // Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
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 // Copyright (C) 2011 - 2012 Andrzej Krzemienski.
23 // Use, modification, and distribution is subject to the Boost Software
24 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
25 // http://www.boost.org/LICENSE_1_0.txt)
26 //
27 // The idea and interface is based on Boost.Optional library
28 // authored by Fernando Luis Cacciola Carballal
29 
30 # ifndef SOL_OPTIONAL_IMPLEMENTATION_HPP
31 # define SOL_OPTIONAL_IMPLEMENTATION_HPP
32 
33 # include <utility>
34 # include <type_traits>
35 # include <initializer_list>
36 # include <cassert>
37 # include <functional>
38 # include <string>
39 # include <stdexcept>
40 #ifdef SOL_NO_EXCEPTIONS
41 #include <cstdlib>
42 #endif // Exceptions
43 
44 # define TR2_OPTIONAL_REQUIRES(...) typename ::std::enable_if<__VA_ARGS__::value, bool>::type = false
45 
46 # if defined __GNUC__ // NOTE: GNUC is also defined for Clang
47 #   if (__GNUC__ >= 5)
48 #     define TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
49 #     define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
50 #   elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
51 #     define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
52 #   elif (__GNUC__ > 4)
53 #     define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
54 #   endif
55 #
56 #   if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)
57 #     define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
58 #   elif (__GNUC__ > 4)
59 #     define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
60 #   endif
61 #
62 #   if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)
63 #     define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
64 #   elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)
65 #     define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
66 #   elif (__GNUC__ > 4)
67 #     define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
68 #   endif
69 # endif
70 #
71 # if defined __clang_major__
72 #   if (__clang_major__ == 3 && __clang_minor__ >= 5)
73 #     define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
74 #   elif (__clang_major__ > 3)
75 #     define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
76 #   endif
77 #   if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
78 #     define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
79 #   elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
80 #     define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
81 #   endif
82 # endif
83 #
84 # if defined _MSC_VER
85 #   if (_MSC_VER >= 1900)
86 #     define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
87 #   endif
88 # endif
89 
90 # if defined __clang__
91 #   if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9)
92 #     define OPTIONAL_HAS_THIS_RVALUE_REFS 1
93 #   else
94 #     define OPTIONAL_HAS_THIS_RVALUE_REFS 0
95 #   endif
96 # elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
97 #   define OPTIONAL_HAS_THIS_RVALUE_REFS 1
98 # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
99 #   define OPTIONAL_HAS_THIS_RVALUE_REFS 1
100 # else
101 #   define OPTIONAL_HAS_THIS_RVALUE_REFS 0
102 # endif
103 
104 
105 # if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
106 #   define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
107 #   define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
108 # else
109 #   define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
110 #   define OPTIONAL_CONSTEXPR_INIT_LIST
111 # endif
112 
113 # if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || (defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L))
114 #   define OPTIONAL_HAS_MOVE_ACCESSORS 1
115 # else
116 #   define OPTIONAL_HAS_MOVE_ACCESSORS 0
117 # endif
118 
119 # // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr
120 # if defined(TR2_OPTIONAL_MSVC_2015_AND_HIGHER___) || ((defined __cplusplus) && (__cplusplus == 201103L))
121 #   define OPTIONAL_MUTABLE_CONSTEXPR
122 # else
123 #   define OPTIONAL_MUTABLE_CONSTEXPR constexpr
124 # endif
125 
126 # if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
127 #pragma warning( push )
128 #pragma warning( disable : 4814 )
129 #endif
130 
131 namespace sol {
132 
133 	// BEGIN workaround for missing is_trivially_destructible
134 # if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
135 	// leave it: it is already there
136 # elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
137 	// leave it: it is already there
138 # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
139 	// leave it: it is already there
140 # elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
141 	// leave it: the user doesn't want it
142 # else
143 	template <typename T>
144 	using is_trivially_destructible = ::std::has_trivial_destructor<T>;
145 # endif
146 	// END workaround for missing is_trivially_destructible
147 
148 # if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___)
149 	// leave it; our metafunctions are already defined.
150 # elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
151 	// leave it; our metafunctions are already defined.
152 # elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
153 	// leave it: it is already there
154 # elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
155 	// leave it: the user doesn't want it
156 # else
157 
158 
159 // workaround for missing traits in GCC and CLANG
160 	template <class T>
161 	struct is_nothrow_move_constructible
162 	{
163 		constexpr static bool value = ::std::is_nothrow_constructible<T, T&&>::value;
164 	};
165 
166 
167 	template <class T, class U>
168 	struct is_assignable
169 	{
170 		template <class X, class Y>
171 		constexpr static bool has_assign(...) { return false; }
172 
173 		template <class X, class Y, size_t S = sizeof((::std::declval<X>() = ::std::declval<Y>(), true)) >
174 		// the comma operator is necessary for the cases where operator= returns void
175 		constexpr static bool has_assign(bool) { return true; }
176 
177 		constexpr static bool value = has_assign<T, U>(true);
178 	};
179 
180 
181 	template <class T>
182 	struct is_nothrow_move_assignable
183 	{
184 		template <class X, bool has_any_move_assign>
185 		struct has_nothrow_move_assign {
186 			constexpr static bool value = false;
187 		};
188 
189 		template <class X>
190 		struct has_nothrow_move_assign<X, true> {
191 			constexpr static bool value = noexcept(::std::declval<X&>() = ::std::declval<X&&>());
192 		};
193 
194 		constexpr static bool value = has_nothrow_move_assign<T, is_assignable<T&, T&&>::value>::value;
195 	};
196 	// end workaround
197 
198 
199 # endif
200 
201 
202 
203 // 20.5.4, optional for object types
204 	template <class T> class optional;
205 
206 	// 20.5.5, optional for lvalue reference types
207 	template <class T> class optional<T&>;
208 
209 
210 	// workaround: std utility functions aren't constexpr yet
constexpr_forward(typename::std::remove_reference<T>::type & t)211 	template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type& t) noexcept
212 	{
213 		return static_cast<T&&>(t);
214 	}
215 
constexpr_forward(typename::std::remove_reference<T>::type && t)216 	template <class T> inline constexpr T&& constexpr_forward(typename ::std::remove_reference<T>::type&& t) noexcept
217 	{
218 		static_assert(!::std::is_lvalue_reference<T>::value, "!!");
219 		return static_cast<T&&>(t);
220 	}
221 
constexpr_move(T && t)222 	template <class T> inline constexpr typename ::std::remove_reference<T>::type&& constexpr_move(T&& t) noexcept
223 	{
224 		return static_cast<typename ::std::remove_reference<T>::type&&>(t);
225 	}
226 
227 
228 #if defined NDEBUG
229 # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
230 #else
231 # define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
232 #endif
233 
234 
235 	namespace detail_
236 	{
237 
238 		// static_addressof: a constexpr version of addressof
239 		template <typename T>
240 		struct has_overloaded_addressof
241 		{
242 			template <class X>
has_overloadsol::detail_::has_overloaded_addressof243 			constexpr static bool has_overload(...) { return false; }
244 
245 			template <class X, size_t S = sizeof(::std::declval<X&>().operator&()) >
has_overloadsol::detail_::has_overloaded_addressof246 			constexpr static bool has_overload(bool) { return true; }
247 
248 			constexpr static bool value = has_overload<T>(true);
249 		};
250 
251 		template <typename T, TR2_OPTIONAL_REQUIRES(!has_overloaded_addressof<T>)>
static_addressof(T & ref)252 		constexpr T* static_addressof(T& ref)
253 		{
254 			return &ref;
255 		}
256 
257 		template <typename T, TR2_OPTIONAL_REQUIRES(has_overloaded_addressof<T>)>
258 		T* static_addressof(T& ref)
259 		{
260 			return ::std::addressof(ref);
261 		}
262 
263 
264 		// the call to convert<A>(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
265 		template <class U>
convert(U v)266 		constexpr U convert(U v) { return v; }
267 
268 	} // namespace detail_
269 
270 	constexpr struct trivial_init_t {} trivial_init{};
271 
272 	// 20.5.7, Disengaged state indicator
273 	struct nullopt_t
274 	{
275 		struct init {};
nullopt_tsol::nullopt_t276 		constexpr explicit nullopt_t(init) {}
277 	};
278 	constexpr nullopt_t nullopt{ nullopt_t::init() };
279 
280 
281 	// 20.5.8, class bad_optional_access
282 	class bad_optional_access : public ::std::logic_error {
283 	public:
bad_optional_access(const::std::string & what_arg)284 		explicit bad_optional_access(const ::std::string& what_arg) : ::std::logic_error{ what_arg } {}
bad_optional_access(const char * what_arg)285 		explicit bad_optional_access(const char* what_arg) : ::std::logic_error{ what_arg } {}
286 	};
287 
288 
289 	template <class T>
290 	struct alignas(T) optional_base {
291 		char storage_[sizeof(T)];
292 		bool init_;
293 
optional_basesol::optional_base294 		constexpr optional_base() noexcept : storage_(), init_(false) {};
295 
optional_basesol::optional_base296 		explicit optional_base(const T& v) : storage_(), init_(true) {
297 			new (&storage())T(v);
298 		}
299 
optional_basesol::optional_base300 		explicit optional_base(T&& v) : storage_(), init_(true) {
301 			new (&storage())T(constexpr_move(v));
302 		}
303 
optional_basesol::optional_base304 		template <class... Args> explicit optional_base(in_place_t, Args&&... args)
305 			: init_(true), storage_() {
306 			new (&storage())T(constexpr_forward<Args>(args)...);
307 		}
308 
309 		template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
optional_basesol::optional_base310 		explicit optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
311 			: init_(true), storage_() {
312 			new (&storage())T(il, constexpr_forward<Args>(args)...);
313 		}
314 #if defined __GNUC__
315 #pragma GCC diagnostic push
316 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
317 #endif
storagesol::optional_base318 		T& storage() {
319 			return *reinterpret_cast<T*>(&storage_[0]);
320 		}
321 
storagesol::optional_base322 		constexpr const T& storage() const {
323 			return *reinterpret_cast<T const*>(&storage_[0]);
324 		}
325 #if defined __GNUC__
326 #pragma GCC diagnostic pop
327 #endif
328 
~optional_basesol::optional_base329 		~optional_base() { if (init_) { storage().T::~T(); } }
330 	};
331 
332 #if defined __GNUC__ && !defined TR2_OPTIONAL_GCC_5_0_AND_HIGHER___
333 	// Sorry, GCC 4.x; you're just a piece of shit
334 	template <typename T>
335 	using constexpr_optional_base = optional_base<T>;
336 #else
337 	template <class T>
338 	struct alignas(T) constexpr_optional_base {
339 		char storage_[sizeof(T)];
340 		bool init_;
constexpr_optional_basesol::constexpr_optional_base341 		constexpr constexpr_optional_base() noexcept : storage_(), init_(false) {}
342 
constexpr_optional_basesol::constexpr_optional_base343 		explicit constexpr constexpr_optional_base(const T& v) : storage_(), init_(true) {
344 			new (&storage())T(v);
345 		}
346 
constexpr_optional_basesol::constexpr_optional_base347 		explicit constexpr constexpr_optional_base(T&& v) : storage_(), init_(true) {
348 			new (&storage())T(constexpr_move(v));
349 		}
350 
constexpr_optional_basesol::constexpr_optional_base351 		template <class... Args> explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
352 			: init_(true), storage_() {
353 			new (&storage())T(constexpr_forward<Args>(args)...);
354 		}
355 
356 		template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
constexpr_optional_basesol::constexpr_optional_base357 		OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, ::std::initializer_list<U> il, Args&&... args)
358 			: init_(true), storage_() {
359 			new (&storage())T(il, constexpr_forward<Args>(args)...);
360 		}
361 
362 #if defined __GNUC__
363 #pragma GCC diagnostic push
364 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
365 #endif
storagesol::constexpr_optional_base366 		T& storage() {
367 			return (*reinterpret_cast<T*>(&storage_[0]));
368 		}
369 
storagesol::constexpr_optional_base370 		constexpr const T& storage() const {
371 			return (*reinterpret_cast<T const*>(&storage_[0]));
372 		}
373 #if defined __GNUC__
374 #pragma GCC diagnostic pop
375 #endif
376 
377 		~constexpr_optional_base() = default;
378 	};
379 #endif
380 
381 	template <class T>
382 	using OptionalBase = typename ::std::conditional<
383 		::std::is_trivially_destructible<T>::value,
384 		constexpr_optional_base<typename ::std::remove_const<T>::type>,
385 		optional_base<typename ::std::remove_const<T>::type>
386 	>::type;
387 
388 
389 
390 	template <class T>
391 	class optional : private OptionalBase<T>
392 	{
393 		static_assert(!::std::is_same<typename ::std::decay<T>::type, nullopt_t>::value, "bad T");
394 		static_assert(!::std::is_same<typename ::std::decay<T>::type, in_place_t>::value, "bad T");
395 
396 
initialized() const397 		constexpr bool initialized() const noexcept { return OptionalBase<T>::init_; }
dataptr()398 		typename ::std::remove_const<T>::type* dataptr() { return ::std::addressof(OptionalBase<T>::storage()); }
dataptr() const399 		constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase<T>::storage()); }
400 
401 # if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
contained_val() const402 		constexpr const T& contained_val() const& { return OptionalBase<T>::storage(); }
403 #   if OPTIONAL_HAS_MOVE_ACCESSORS == 1
contained_val()404 		OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
contained_val()405 		OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase<T>::storage(); }
406 #   else
contained_val()407 		T& contained_val() & { return OptionalBase<T>::storage(); }
contained_val()408 		T&& contained_val() && { return ::std::move(OptionalBase<T>::storage()); }
409 #   endif
410 # else
contained_val() const411 		constexpr const T& contained_val() const { return OptionalBase<T>::storage(); }
contained_val()412 		T& contained_val() { return OptionalBase<T>::storage(); }
413 # endif
414 
clear()415 		void clear() noexcept {
416 			if (initialized()) dataptr()->T::~T();
417 			OptionalBase<T>::init_ = false;
418 		}
419 
420 		template <class... Args>
initialize(Args &&...args)421 		void initialize(Args&&... args) noexcept(noexcept(T(::std::forward<Args>(args)...)))
422 		{
423 			assert(!OptionalBase<T>::init_);
424 			::new (static_cast<void*>(dataptr())) T(::std::forward<Args>(args)...);
425 			OptionalBase<T>::init_ = true;
426 		}
427 
428 		template <class U, class... Args>
initialize(::std::initializer_list<U> il,Args &&...args)429 		void initialize(::std::initializer_list<U> il, Args&&... args) noexcept(noexcept(T(il, ::std::forward<Args>(args)...)))
430 		{
431 			assert(!OptionalBase<T>::init_);
432 			::new (static_cast<void*>(dataptr())) T(il, ::std::forward<Args>(args)...);
433 			OptionalBase<T>::init_ = true;
434 		}
435 
436 	public:
437 		typedef T value_type;
438 
439 		// 20.5.5.1, constructors
optional()440 		constexpr optional() noexcept : OptionalBase<T>() {};
optional(nullopt_t)441 		constexpr optional(nullopt_t) noexcept : OptionalBase<T>() {};
442 
optional(const optional & rhs)443 		optional(const optional& rhs)
444 			: OptionalBase<T>()
445 		{
446 			if (rhs.initialized()) {
447 				::new (static_cast<void*>(dataptr())) T(*rhs);
448 				OptionalBase<T>::init_ = true;
449 			}
450 		}
451 
optional(const optional<T &> & rhs)452 		optional(const optional<T&>& rhs) : optional()
453 		{
454 			if (rhs) {
455 				::new (static_cast<void*>(dataptr())) T(*rhs);
456 				OptionalBase<T>::init_ = true;
457 			}
458 		}
459 
460 
optional(optional && rhs)461 		optional(optional&& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value)
462 			: OptionalBase<T>()
463 		{
464 			if (rhs.initialized()) {
465 				::new (static_cast<void*>(dataptr())) T(::std::move(*rhs));
466 				OptionalBase<T>::init_ = true;
467 			}
468 		}
469 
optional(const T & v)470 		constexpr optional(const T& v) : OptionalBase<T>(v) {}
471 
optional(T && v)472 		constexpr optional(T&& v) : OptionalBase<T>(constexpr_move(v)) {}
473 
474 		template <class... Args>
optional(in_place_t,Args &&...args)475 		explicit constexpr optional(in_place_t, Args&&... args)
476 			: OptionalBase<T>(in_place, constexpr_forward<Args>(args)...) {}
477 
478 		template <class U, class... Args, TR2_OPTIONAL_REQUIRES(::std::is_constructible<T, ::std::initializer_list<U>>)>
optional(in_place_t,::std::initializer_list<U> il,Args &&...args)479 		OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, ::std::initializer_list<U> il, Args&&... args)
480 			: OptionalBase<T>(in_place, il, constexpr_forward<Args>(args)...) {}
481 
482 		// 20.5.4.2, Destructor
483 		~optional() = default;
484 
485 		// 20.5.4.3, assignment
operator =(nullopt_t)486 		optional& operator=(nullopt_t) noexcept
487 		{
488 			clear();
489 			return *this;
490 		}
491 
operator =(const optional & rhs)492 		optional& operator=(const optional& rhs)
493 		{
494 			if (initialized() == true && rhs.initialized() == false) clear();
495 			else if (initialized() == false && rhs.initialized() == true)  initialize(*rhs);
496 			else if (initialized() == true && rhs.initialized() == true)  contained_val() = *rhs;
497 			return *this;
498 		}
499 
operator =(optional && rhs)500 		optional& operator=(optional&& rhs)
501 			noexcept(::std::is_nothrow_move_assignable<T>::value && ::std::is_nothrow_move_constructible<T>::value)
502 		{
503 			if (initialized() == true && rhs.initialized() == false) clear();
504 			else if (initialized() == false && rhs.initialized() == true)  initialize(::std::move(*rhs));
505 			else if (initialized() == true && rhs.initialized() == true)  contained_val() = ::std::move(*rhs);
506 			return *this;
507 		}
508 
509 		template <class U>
operator =(U && v)510 		auto operator=(U&& v)
511 			-> typename ::std::enable_if
512 			<
513 			::std::is_same<typename ::std::decay<U>::type, T>::value,
514 			optional&
515 			>::type
516 		{
517 			if (initialized()) { contained_val() = ::std::forward<U>(v); }
518 			else { initialize(::std::forward<U>(v)); }
519 			return *this;
520 		}
521 
522 
523 		template <class... Args>
emplace(Args &&...args)524 		void emplace(Args&&... args)
525 		{
526 			clear();
527 			initialize(::std::forward<Args>(args)...);
528 		}
529 
530 		template <class U, class... Args>
emplace(::std::initializer_list<U> il,Args &&...args)531 		void emplace(::std::initializer_list<U> il, Args&&... args)
532 		{
533 			clear();
534 			initialize<U, Args...>(il, ::std::forward<Args>(args)...);
535 		}
536 
537 		// 20.5.4.4, Swap
swap(optional<T> & rhs)538 		void swap(optional<T>& rhs) noexcept(::std::is_nothrow_move_constructible<T>::value && noexcept(swap(::std::declval<T&>(), ::std::declval<T&>())))
539 		{
540 			if (initialized() == true && rhs.initialized() == false) { rhs.initialize(::std::move(**this)); clear(); }
541 			else if (initialized() == false && rhs.initialized() == true) { initialize(::std::move(*rhs)); rhs.clear(); }
542 			else if (initialized() == true && rhs.initialized() == true) { using ::std::swap; swap(**this, *rhs); }
543 		}
544 
545 		// 20.5.4.5, Observers
546 
operator bool() const547 		explicit constexpr operator bool() const noexcept { return initialized(); }
548 
operator ->() const549 		constexpr T const* operator ->() const {
550 			return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
551 		}
552 
553 # if OPTIONAL_HAS_MOVE_ACCESSORS == 1
554 
operator ->()555 		OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
556 			assert(initialized());
557 			return dataptr();
558 		}
559 
operator *() const560 		constexpr T const& operator *() const& {
561 			return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
562 		}
563 
operator *()564 		OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
565 			assert(initialized());
566 			return contained_val();
567 		}
568 
operator *()569 		OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
570 			assert(initialized());
571 			return constexpr_move(contained_val());
572 		}
573 
value() const574 		constexpr T const& value() const& {
575 			return initialized() ?
576 				contained_val()
577 #ifdef SOL_NO_EXCEPTIONS
578 				// we can't abort here
579 				// because there's no constexpr abort
580 				: *(T*)nullptr;
581 #else
582 				: (throw bad_optional_access("bad optional access"), contained_val());
583 #endif
584 		}
585 
value()586 		OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
587 			return initialized() ?
588 				contained_val()
589 #ifdef SOL_NO_EXCEPTIONS
590 				: *(T*)nullptr;
591 #else
592 				: (throw bad_optional_access("bad optional access"), contained_val());
593 #endif
594 		}
595 
value()596 		OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
597 			return initialized() ?
598 				contained_val()
599 #ifdef SOL_NO_EXCEPTIONS
600 				// we can't abort here
601 				// because there's no constexpr abort
602 				: std::move(*(T*)nullptr);
603 #else
604 				: (throw bad_optional_access("bad optional access"), contained_val());
605 #endif
606 		}
607 
608 # else
609 
operator ->()610 		T* operator ->() {
611 			assert(initialized());
612 			return dataptr();
613 		}
614 
operator *() const615 		constexpr T const& operator *() const {
616 			return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
617 		}
618 
operator *()619 		T& operator *() {
620 			assert(initialized());
621 			return contained_val();
622 		}
623 
value() const624 		constexpr T const& value() const {
625 			return initialized() ?
626 				contained_val()
627 #ifdef SOL_NO_EXCEPTIONS
628 				// we can't abort here
629 				// because there's no constexpr abort
630 				: *(T*)nullptr;
631 #else
632 				: (throw bad_optional_access("bad optional access"), contained_val());
633 #endif
634 		}
635 
value()636 		T& value() {
637 			return initialized() ?
638 				contained_val()
639 #ifdef SOL_NO_EXCEPTIONS
640 				// we can abort here
641 				// but the others are constexpr, so we can't...
642 				: (std::abort(), *(T*)nullptr);
643 #else
644 				: (throw bad_optional_access("bad optional access"), contained_val());
645 #endif
646 		}
647 
648 # endif
649 
650 # if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
651 
652 		template <class V>
value_or(V && v) const653 		constexpr T value_or(V&& v) const&
654 		{
655 			return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
656 		}
657 
658 #   if OPTIONAL_HAS_MOVE_ACCESSORS == 1
659 
660 		template <class V>
value_or(V && v)661 		OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
662 		{
663 			return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
664 		}
665 
666 #   else
667 
668 		template <class V>
value_or(V && v)669 		T value_or(V&& v) &&
670 		{
671 			return *this ? constexpr_move(const_cast<optional<T>&>(*this).contained_val()) : detail_::convert<T>(constexpr_forward<V>(v));
672 		}
673 
674 #   endif
675 
676 # else
677 
678 		template <class V>
value_or(V && v) const679 		constexpr T value_or(V&& v) const
680 		{
681 			return *this ? **this : detail_::convert<T>(constexpr_forward<V>(v));
682 		}
683 
684 # endif
685 
686 	};
687 
688 
689 	template <class T>
690 	class optional<T&>
691 	{
692 		static_assert(!::std::is_same<T, nullopt_t>::value, "bad T");
693 		static_assert(!::std::is_same<T, in_place_t>::value, "bad T");
694 		T* ref;
695 
696 	public:
697 
698 		// 20.5.5.1, construction/destruction
optional()699 		constexpr optional() noexcept : ref(nullptr) {}
700 
optional(nullopt_t)701 		constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
702 
optional(T & v)703 		constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
704 
705 		optional(T&&) = delete;
706 
optional(const optional & rhs)707 		constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
708 
optional(in_place_t,T & v)709 		explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
710 
711 		explicit optional(in_place_t, T&&) = delete;
712 
713 		~optional() = default;
714 
715 		// 20.5.5.2, mutation
operator =(nullopt_t)716 		optional& operator=(nullopt_t) noexcept {
717 			ref = nullptr;
718 			return *this;
719 		}
720 
721 		// optional& operator=(const optional& rhs) noexcept {
722 		  // ref = rhs.ref;
723 		  // return *this;
724 		// }
725 
726 		// optional& operator=(optional&& rhs) noexcept {
727 		  // ref = rhs.ref;
728 		  // return *this;
729 		// }
730 
731 		template <typename U>
operator =(U && rhs)732 		auto operator=(U&& rhs) noexcept
733 			-> typename ::std::enable_if
734 			<
735 			::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
736 			optional&
737 			>::type
738 		{
739 			ref = rhs.ref;
740 			return *this;
741 		}
742 
743 		template <typename U>
744 		auto operator=(U&& rhs) noexcept
745 			-> typename ::std::enable_if
746 			<
747 			!::std::is_same<typename ::std::decay<U>::type, optional<T&>>::value,
748 			optional&
749 			>::type
750 			= delete;
751 
emplace(T & v)752 		void emplace(T& v) noexcept {
753 			ref = detail_::static_addressof(v);
754 		}
755 
756 		void emplace(T&&) = delete;
757 
758 
swap(optional<T &> & rhs)759 		void swap(optional<T&>& rhs) noexcept
760 		{
761 			::std::swap(ref, rhs.ref);
762 		}
763 
764 		// 20.5.5.3, observers
operator ->() const765 		constexpr T* operator->() const {
766 			return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
767 		}
768 
operator *() const769 		constexpr T& operator*() const {
770 			return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
771 		}
772 
value() const773 		constexpr T& value() const {
774 			return ref ?
775 				*ref
776 #ifdef SOL_NO_EXCEPTIONS
777 				// we can't abort here
778 				// because there's no constexpr abort
779 				: *(T*)nullptr;
780 #else
781 				: throw bad_optional_access("bad optional access");
782 #endif
783 		}
784 
operator bool() const785 		explicit constexpr operator bool() const noexcept {
786 			return ref != nullptr;
787 		}
788 
789 		template <typename V>
value_or(V && v) const790 		constexpr T& value_or(V&& v) const
791 		{
792 			return *this ? **this : detail_::convert<T&>(constexpr_forward<V>(v));
793 		}
794 	};
795 
796 
797 	template <class T>
798 	class optional<T&&>
799 	{
800 		static_assert(sizeof(T) == 0, "optional rvalue references disallowed");
801 	};
802 
803 
804 	// 20.5.8, Relational operators
operator ==(const optional<T> & x,const optional<T> & y)805 	template <class T> constexpr bool operator==(const optional<T>& x, const optional<T>& y)
806 	{
807 		return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
808 	}
809 
operator !=(const optional<T> & x,const optional<T> & y)810 	template <class T> constexpr bool operator!=(const optional<T>& x, const optional<T>& y)
811 	{
812 		return !(x == y);
813 	}
814 
operator <(const optional<T> & x,const optional<T> & y)815 	template <class T> constexpr bool operator<(const optional<T>& x, const optional<T>& y)
816 	{
817 		return (!y) ? false : (!x) ? true : *x < *y;
818 	}
819 
operator >(const optional<T> & x,const optional<T> & y)820 	template <class T> constexpr bool operator>(const optional<T>& x, const optional<T>& y)
821 	{
822 		return (y < x);
823 	}
824 
operator <=(const optional<T> & x,const optional<T> & y)825 	template <class T> constexpr bool operator<=(const optional<T>& x, const optional<T>& y)
826 	{
827 		return !(y < x);
828 	}
829 
operator >=(const optional<T> & x,const optional<T> & y)830 	template <class T> constexpr bool operator>=(const optional<T>& x, const optional<T>& y)
831 	{
832 		return !(x < y);
833 	}
834 
835 
836 	// 20.5.9, Comparison with nullopt
operator ==(const optional<T> & x,nullopt_t)837 	template <class T> constexpr bool operator==(const optional<T>& x, nullopt_t) noexcept
838 	{
839 		return (!x);
840 	}
841 
operator ==(nullopt_t,const optional<T> & x)842 	template <class T> constexpr bool operator==(nullopt_t, const optional<T>& x) noexcept
843 	{
844 		return (!x);
845 	}
846 
operator !=(const optional<T> & x,nullopt_t)847 	template <class T> constexpr bool operator!=(const optional<T>& x, nullopt_t) noexcept
848 	{
849 		return bool(x);
850 	}
851 
operator !=(nullopt_t,const optional<T> & x)852 	template <class T> constexpr bool operator!=(nullopt_t, const optional<T>& x) noexcept
853 	{
854 		return bool(x);
855 	}
856 
operator <(const optional<T> &,nullopt_t)857 	template <class T> constexpr bool operator<(const optional<T>&, nullopt_t) noexcept
858 	{
859 		return false;
860 	}
861 
operator <(nullopt_t,const optional<T> & x)862 	template <class T> constexpr bool operator<(nullopt_t, const optional<T>& x) noexcept
863 	{
864 		return bool(x);
865 	}
866 
operator <=(const optional<T> & x,nullopt_t)867 	template <class T> constexpr bool operator<=(const optional<T>& x, nullopt_t) noexcept
868 	{
869 		return (!x);
870 	}
871 
operator <=(nullopt_t,const optional<T> &)872 	template <class T> constexpr bool operator<=(nullopt_t, const optional<T>&) noexcept
873 	{
874 		return true;
875 	}
876 
operator >(const optional<T> & x,nullopt_t)877 	template <class T> constexpr bool operator>(const optional<T>& x, nullopt_t) noexcept
878 	{
879 		return bool(x);
880 	}
881 
operator >(nullopt_t,const optional<T> &)882 	template <class T> constexpr bool operator>(nullopt_t, const optional<T>&) noexcept
883 	{
884 		return false;
885 	}
886 
operator >=(const optional<T> &,nullopt_t)887 	template <class T> constexpr bool operator>=(const optional<T>&, nullopt_t) noexcept
888 	{
889 		return true;
890 	}
891 
operator >=(nullopt_t,const optional<T> & x)892 	template <class T> constexpr bool operator>=(nullopt_t, const optional<T>& x) noexcept
893 	{
894 		return (!x);
895 	}
896 
897 
898 
899 	// 20.5.10, Comparison with T
operator ==(const optional<T> & x,const T & v)900 	template <class T> constexpr bool operator==(const optional<T>& x, const T& v)
901 	{
902 		return bool(x) ? *x == v : false;
903 	}
904 
operator ==(const T & v,const optional<T> & x)905 	template <class T> constexpr bool operator==(const T& v, const optional<T>& x)
906 	{
907 		return bool(x) ? v == *x : false;
908 	}
909 
operator !=(const optional<T> & x,const T & v)910 	template <class T> constexpr bool operator!=(const optional<T>& x, const T& v)
911 	{
912 		return bool(x) ? *x != v : true;
913 	}
914 
operator !=(const T & v,const optional<T> & x)915 	template <class T> constexpr bool operator!=(const T& v, const optional<T>& x)
916 	{
917 		return bool(x) ? v != *x : true;
918 	}
919 
operator <(const optional<T> & x,const T & v)920 	template <class T> constexpr bool operator<(const optional<T>& x, const T& v)
921 	{
922 		return bool(x) ? *x < v : true;
923 	}
924 
operator >(const T & v,const optional<T> & x)925 	template <class T> constexpr bool operator>(const T& v, const optional<T>& x)
926 	{
927 		return bool(x) ? v > *x : true;
928 	}
929 
operator >(const optional<T> & x,const T & v)930 	template <class T> constexpr bool operator>(const optional<T>& x, const T& v)
931 	{
932 		return bool(x) ? *x > v : false;
933 	}
934 
operator <(const T & v,const optional<T> & x)935 	template <class T> constexpr bool operator<(const T& v, const optional<T>& x)
936 	{
937 		return bool(x) ? v < *x : false;
938 	}
939 
operator >=(const optional<T> & x,const T & v)940 	template <class T> constexpr bool operator>=(const optional<T>& x, const T& v)
941 	{
942 		return bool(x) ? *x >= v : false;
943 	}
944 
operator <=(const T & v,const optional<T> & x)945 	template <class T> constexpr bool operator<=(const T& v, const optional<T>& x)
946 	{
947 		return bool(x) ? v <= *x : false;
948 	}
949 
operator <=(const optional<T> & x,const T & v)950 	template <class T> constexpr bool operator<=(const optional<T>& x, const T& v)
951 	{
952 		return bool(x) ? *x <= v : true;
953 	}
954 
operator >=(const T & v,const optional<T> & x)955 	template <class T> constexpr bool operator>=(const T& v, const optional<T>& x)
956 	{
957 		return bool(x) ? v >= *x : true;
958 	}
959 
960 
961 	// Comparison of optional<T&> with T
operator ==(const optional<T &> & x,const T & v)962 	template <class T> constexpr bool operator==(const optional<T&>& x, const T& v)
963 	{
964 		return bool(x) ? *x == v : false;
965 	}
966 
operator ==(const T & v,const optional<T &> & x)967 	template <class T> constexpr bool operator==(const T& v, const optional<T&>& x)
968 	{
969 		return bool(x) ? v == *x : false;
970 	}
971 
operator !=(const optional<T &> & x,const T & v)972 	template <class T> constexpr bool operator!=(const optional<T&>& x, const T& v)
973 	{
974 		return bool(x) ? *x != v : true;
975 	}
976 
operator !=(const T & v,const optional<T &> & x)977 	template <class T> constexpr bool operator!=(const T& v, const optional<T&>& x)
978 	{
979 		return bool(x) ? v != *x : true;
980 	}
981 
operator <(const optional<T &> & x,const T & v)982 	template <class T> constexpr bool operator<(const optional<T&>& x, const T& v)
983 	{
984 		return bool(x) ? *x < v : true;
985 	}
986 
operator >(const T & v,const optional<T &> & x)987 	template <class T> constexpr bool operator>(const T& v, const optional<T&>& x)
988 	{
989 		return bool(x) ? v > *x : true;
990 	}
991 
operator >(const optional<T &> & x,const T & v)992 	template <class T> constexpr bool operator>(const optional<T&>& x, const T& v)
993 	{
994 		return bool(x) ? *x > v : false;
995 	}
996 
operator <(const T & v,const optional<T &> & x)997 	template <class T> constexpr bool operator<(const T& v, const optional<T&>& x)
998 	{
999 		return bool(x) ? v < *x : false;
1000 	}
1001 
operator >=(const optional<T &> & x,const T & v)1002 	template <class T> constexpr bool operator>=(const optional<T&>& x, const T& v)
1003 	{
1004 		return bool(x) ? *x >= v : false;
1005 	}
1006 
operator <=(const T & v,const optional<T &> & x)1007 	template <class T> constexpr bool operator<=(const T& v, const optional<T&>& x)
1008 	{
1009 		return bool(x) ? v <= *x : false;
1010 	}
1011 
operator <=(const optional<T &> & x,const T & v)1012 	template <class T> constexpr bool operator<=(const optional<T&>& x, const T& v)
1013 	{
1014 		return bool(x) ? *x <= v : true;
1015 	}
1016 
operator >=(const T & v,const optional<T &> & x)1017 	template <class T> constexpr bool operator>=(const T& v, const optional<T&>& x)
1018 	{
1019 		return bool(x) ? v >= *x : true;
1020 	}
1021 
1022 	// Comparison of optional<T const&> with T
operator ==(const optional<const T &> & x,const T & v)1023 	template <class T> constexpr bool operator==(const optional<const T&>& x, const T& v)
1024 	{
1025 		return bool(x) ? *x == v : false;
1026 	}
1027 
operator ==(const T & v,const optional<const T &> & x)1028 	template <class T> constexpr bool operator==(const T& v, const optional<const T&>& x)
1029 	{
1030 		return bool(x) ? v == *x : false;
1031 	}
1032 
operator !=(const optional<const T &> & x,const T & v)1033 	template <class T> constexpr bool operator!=(const optional<const T&>& x, const T& v)
1034 	{
1035 		return bool(x) ? *x != v : true;
1036 	}
1037 
operator !=(const T & v,const optional<const T &> & x)1038 	template <class T> constexpr bool operator!=(const T& v, const optional<const T&>& x)
1039 	{
1040 		return bool(x) ? v != *x : true;
1041 	}
1042 
operator <(const optional<const T &> & x,const T & v)1043 	template <class T> constexpr bool operator<(const optional<const T&>& x, const T& v)
1044 	{
1045 		return bool(x) ? *x < v : true;
1046 	}
1047 
operator >(const T & v,const optional<const T &> & x)1048 	template <class T> constexpr bool operator>(const T& v, const optional<const T&>& x)
1049 	{
1050 		return bool(x) ? v > *x : true;
1051 	}
1052 
operator >(const optional<const T &> & x,const T & v)1053 	template <class T> constexpr bool operator>(const optional<const T&>& x, const T& v)
1054 	{
1055 		return bool(x) ? *x > v : false;
1056 	}
1057 
operator <(const T & v,const optional<const T &> & x)1058 	template <class T> constexpr bool operator<(const T& v, const optional<const T&>& x)
1059 	{
1060 		return bool(x) ? v < *x : false;
1061 	}
1062 
operator >=(const optional<const T &> & x,const T & v)1063 	template <class T> constexpr bool operator>=(const optional<const T&>& x, const T& v)
1064 	{
1065 		return bool(x) ? *x >= v : false;
1066 	}
1067 
operator <=(const T & v,const optional<const T &> & x)1068 	template <class T> constexpr bool operator<=(const T& v, const optional<const T&>& x)
1069 	{
1070 		return bool(x) ? v <= *x : false;
1071 	}
1072 
operator <=(const optional<const T &> & x,const T & v)1073 	template <class T> constexpr bool operator<=(const optional<const T&>& x, const T& v)
1074 	{
1075 		return bool(x) ? *x <= v : true;
1076 	}
1077 
operator >=(const T & v,const optional<const T &> & x)1078 	template <class T> constexpr bool operator>=(const T& v, const optional<const T&>& x)
1079 	{
1080 		return bool(x) ? v >= *x : true;
1081 	}
1082 
1083 
1084 	// 20.5.12, Specialized algorithms
1085 	template <class T>
swap(optional<T> & x,optional<T> & y)1086 	void swap(optional<T>& x, optional<T>& y) noexcept(noexcept(x.swap(y))) {
1087 		x.swap(y);
1088 	}
1089 
1090 
1091 	template <class T>
make_optional(T && v)1092 	constexpr optional<typename ::std::decay<T>::type> make_optional(T&& v) {
1093 		return optional<typename ::std::decay<T>::type>(constexpr_forward<T>(v));
1094 	}
1095 
1096 	template <class X>
make_optional(::std::reference_wrapper<X> v)1097 	constexpr optional<X&> make_optional(::std::reference_wrapper<X> v) {
1098 		return optional<X&>(v.get());
1099 	}
1100 
1101 
1102 } // namespace
1103 
1104 namespace std
1105 {
1106 	template <typename T>
1107 	struct hash<sol::optional<T>> {
1108 		typedef typename hash<T>::result_type result_type;
1109 		typedef sol::optional<T> argument_type;
1110 
operator ()std::hash1111 		constexpr result_type operator()(argument_type const& arg) const {
1112 			return arg ? ::std::hash<T>{}(*arg) : result_type{};
1113 		}
1114 	};
1115 
1116 	template <typename T>
1117 	struct hash<sol::optional<T&>> {
1118 		typedef typename hash<T>::result_type result_type;
1119 		typedef sol::optional<T&> argument_type;
1120 
operator ()std::hash1121 		constexpr result_type operator()(argument_type const& arg) const {
1122 			return arg ? ::std::hash<T>{}(*arg) : result_type{};
1123 		}
1124 	};
1125 }
1126 
1127 # if defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
1128 #pragma warning( pop )
1129 #endif
1130 
1131 
1132 # undef TR2_OPTIONAL_REQUIRES
1133 # undef TR2_OPTIONAL_ASSERTED_EXPRESSION
1134 
1135 # endif // SOL_OPTIONAL_IMPLEMENTATION_HPP
1136