// The MIT License (MIT)
// Copyright (c) 2013-2021 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Taken from: TartanLlama/optional on Github, because
// holy shit am I done dealing with C++11 constexpr
///
// optional - An implementation of std::optional with extensions
// Written in 2017 by Simon Brand (@TartanLlama)
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to the
// public domain worldwide. This software is distributed without any warranty.
//
// You should have received a copy of the CC0 Public Domain Dedication
// along with this software. If not, see
// .
///
#ifndef SOL_TL_OPTIONAL_HPP
#define SOL_TL_OPTIONAL_HPP
#include 
#include 
#define SOL_TL_OPTIONAL_VERSION_MAJOR 0
#define SOL_TL_OPTIONAL_VERSION_MINOR 5
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#if (defined(_MSC_VER) && _MSC_VER == 1900)
#define SOL_TL_OPTIONAL_MSVC2015
#endif
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
#define SOL_TL_OPTIONAL_GCC49
#endif
#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && !defined(__clang__))
#define SOL_TL_OPTIONAL_GCC54
#endif
#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && !defined(__clang__))
#define SOL_TL_OPTIONAL_GCC55
#endif
#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && !defined(__clang__))
// GCC < 5 doesn't support overloading on const&& for member functions
#define SOL_TL_OPTIONAL_NO_CONSTRR
// GCC < 5 doesn't support some standard C++11 type traits
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::has_trivial_copy_constructor::value
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::has_trivial_copy_assign::value
// This one will be different for GCC 5.7 if it's ever supported
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
// GCC 5 < v < 8 has a bug in is_trivially_copy_constructible which breaks std::vector
// for non-copyable types
#elif (defined(__GNUC__) && __GNUC__ < 8 && !defined(__clang__))
#ifndef SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
#define SOL_TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
namespace sol { namespace detail {
	template 
	struct is_trivially_copy_constructible : std::is_trivially_copy_constructible { };
#ifdef _GLIBCXX_VECTOR
	template 
	struct is_trivially_copy_constructible> : std::is_trivially_copy_constructible { };
#endif
}} // namespace sol::detail
#endif
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) sol::detail::is_trivially_copy_constructible::value
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable::value
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
#else
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) std::is_trivially_copy_constructible::value
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) std::is_trivially_copy_assignable::value
#define SOL_TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
#endif
#if __cplusplus > 201103L
#define SOL_TL_OPTIONAL_CXX14
#endif
// constexpr implies const in C++11, not C++14
#if (__cplusplus == 201103L || defined(SOL_TL_OPTIONAL_MSVC2015) || defined(SOL_TL_OPTIONAL_GCC49))
/// \exclude
#define SOL_TL_OPTIONAL_11_CONSTEXPR
#else
   /// \exclude
#define SOL_TL_OPTIONAL_11_CONSTEXPR constexpr
#endif
namespace sol {
#ifndef SOL_TL_MONOSTATE_INPLACE_MUTEX
#define SOL_TL_MONOSTATE_INPLACE_MUTEX
	/// \brief Used to represent an optional with no data; essentially a bool
	class monostate { };
#endif
	template 
	class optional;
	/// \exclude
	namespace detail {
#ifndef SOL_TL_TRAITS_MUTEX
#define SOL_TL_TRAITS_MUTEX
		// C++14-style aliases for brevity
		template 
		using remove_const_t = typename std::remove_const::type;
		template 
		using remove_reference_t = typename std::remove_reference::type;
		template 
		using decay_t = typename std::decay::type;
		template 
		using enable_if_t = typename std::enable_if::type;
		template 
		using conditional_t = typename std::conditional::type;
		// std::conjunction from C++17
		template 
		struct conjunction : std::true_type { };
		template 
		struct conjunction : B { };
		template 
		struct conjunction : std::conditional, B>::type { };
#if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
#define SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
#endif
// In C++11 mode, there's an issue in libc++'s std::mem_fn
// which results in a hard-error when using it in a noexcept expression
// in some cases. This is a check to workaround the common failing case.
#ifdef SOL_TL_OPTIONAL_LIBCXX_MEM_FN_WORKAROUND
		template 
		struct is_pointer_to_non_const_member_func : std::false_type { };
		template 
		struct is_pointer_to_non_const_member_func : std::true_type { };
		template 
		struct is_pointer_to_non_const_member_func : std::true_type { };
		template 
		struct is_pointer_to_non_const_member_func : std::true_type { };
		template 
		struct is_pointer_to_non_const_member_func : std::true_type { };
		template 
		struct is_pointer_to_non_const_member_func : std::true_type { };
		template 
		struct is_pointer_to_non_const_member_func : std::true_type { };
		template 
		struct is_const_or_const_ref : std::false_type { };
		template 
		struct is_const_or_const_ref : std::true_type { };
		template 
		struct is_const_or_const_ref : std::true_type { };
#endif
		// std::invoke from C++17
		// https://stackoverflow.com/questions/38288042/c11-14-invoke-workaround
		template ::value && is_const_or_const_ref::value)>,
#endif
		     typename = enable_if_t>::value>, int = 0>
		constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::mem_fn(f)(std::forward(args)...)))
		     -> decltype(std::mem_fn(f)(std::forward(args)...)) {
			return std::mem_fn(f)(std::forward(args)...);
		}
		template >::value>>
		constexpr auto invoke(Fn&& f, Args&&... args) noexcept(noexcept(std::forward(f)(std::forward(args)...)))
		     -> decltype(std::forward(f)(std::forward(args)...)) {
			return std::forward(f)(std::forward(args)...);
		}
		// std::invoke_result from C++17
		template 
		struct invoke_result_impl;
		template 
		struct invoke_result_impl(), std::declval()...), void()), Us...> {
			using type = decltype(detail::invoke(std::declval(), std::declval()...));
		};
		template 
		using invoke_result = invoke_result_impl;
		template 
		using invoke_result_t = typename invoke_result::type;
#endif
		// std::void_t from C++17
		template 
		struct voider {
			using type = void;
		};
		template 
		using void_t = typename voider::type;
		// Trait for checking if a type is a sol::optional
		template 
		struct is_optional_impl : std::false_type { };
		template 
		struct is_optional_impl> : std::true_type { };
		template 
		using is_optional = is_optional_impl>;
		// Change void to sol::monostate
		template 
		using fixup_void = conditional_t::value, monostate, U>;
		template >
		using get_map_return = optional>>;
		// Check if invoking F for some Us returns void
		template 
		struct returns_void_impl;
		template 
		struct returns_void_impl>, U...> : std::is_void> { };
		template 
		using returns_void = returns_void_impl;
		template 
		using enable_if_ret_void = enable_if_t::value>;
		template 
		using disable_if_ret_void = enable_if_t::value>;
		template 
		using enable_forward_value = detail::enable_if_t::value && !std::is_same, in_place_t>::value
		     && !std::is_same, detail::decay_t>::value>;
		template 
		using enable_from_other = detail::enable_if_t::value && !std::is_constructible&>::value
		     && !std::is_constructible&&>::value && !std::is_constructible&>::value
		     && !std::is_constructible&&>::value && !std::is_convertible&, T>::value
		     && !std::is_convertible&&, T>::value && !std::is_convertible&, T>::value
		     && !std::is_convertible&&, T>::value>;
		template 
		using enable_assign_forward = detail::enable_if_t, detail::decay_t>::value
		     && !detail::conjunction, std::is_same>>::value && std::is_constructible::value
		     && std::is_assignable::value>;
		template 
		using enable_assign_from_other = detail::enable_if_t::value && std::is_assignable::value
		     && !std::is_constructible&>::value && !std::is_constructible&&>::value
		     && !std::is_constructible&>::value && !std::is_constructible&&>::value
		     && !std::is_convertible&, T>::value && !std::is_convertible&&, T>::value
		     && !std::is_convertible&, T>::value && !std::is_convertible&&, T>::value
		     && !std::is_assignable&>::value && !std::is_assignable&&>::value
		     && !std::is_assignable&>::value && !std::is_assignable&&>::value>;
#ifdef _MSC_VER
		// TODO make a version which works with MSVC
		template 
		struct is_swappable : std::true_type { };
		template 
		struct is_nothrow_swappable : std::true_type { };
#else
		// https://stackoverflow.com/questions/26744589/what-is-a-proper-way-to-implement-is-swappable-to-test-for-the-swappable-concept
		namespace swap_adl_tests {
			// if swap ADL finds this then it would call std::swap otherwise (same
			// signature)
			struct tag { };
			template 
			tag swap(T&, T&);
			template 
			tag swap(T (&a)[N], T (&b)[N]);
			// helper functions to test if an unqualified swap is possible, and if it
			// becomes std::swap
			template 
			std::false_type can_swap(...) noexcept(false);
			template (), std::declval()))>
			std::true_type can_swap(int) noexcept(noexcept(swap(std::declval(), std::declval())));
			template 
			std::false_type uses_std(...);
			template 
			std::is_same(), std::declval())), tag> uses_std(int);
			template 
			struct is_std_swap_noexcept
			: std::integral_constant::value && std::is_nothrow_move_assignable::value> { };
			template 
			struct is_std_swap_noexcept : is_std_swap_noexcept { };
			template 
			struct is_adl_swap_noexcept : std::integral_constant(0))> { };
		} // namespace swap_adl_tests
		template 
		struct is_swappable : std::integral_constant(0))::value
		                                && (!decltype(detail::swap_adl_tests::uses_std(0))::value
		                                     || (std::is_move_assignable::value && std::is_move_constructible::value))> { };
		template 
		struct is_swappable : std::integral_constant(0))::value
		                                            && (!decltype(detail::swap_adl_tests::uses_std(0))::value || is_swappable::value)> { };
		template 
		struct is_nothrow_swappable
		: std::integral_constant::value
		            && ((decltype(detail::swap_adl_tests::uses_std(0))::value&& detail::swap_adl_tests::is_std_swap_noexcept::value)
		                 || (!decltype(detail::swap_adl_tests::uses_std(0))::value&& detail::swap_adl_tests::is_adl_swap_noexcept::value))> { };
#endif
		// The storage base manages the actual storage, and correctly propagates
		// trivial destroyion from T. This case is for when T is not trivially
		// destructible.
		template ::value>
		struct optional_storage_base {
			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) {
			}
			template 
			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward(u)...), m_has_value(true) {
			}
			~optional_storage_base() {
				if (m_has_value) {
					m_value.~T();
					m_has_value = false;
				}
			}
			struct dummy { };
			union {
				dummy m_dummy;
				T m_value;
			};
			bool m_has_value;
		};
		// This case is for when T is trivially destructible.
		template 
		struct optional_storage_base {
			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept : m_dummy(), m_has_value(false) {
			}
			template 
			SOL_TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U&&... u) : m_value(std::forward(u)...), m_has_value(true) {
			}
			// No destructor, so this class is trivially destructible
			struct dummy { };
			union {
				dummy m_dummy;
				T m_value;
			};
			bool m_has_value = false;
		};
		// This base class provides some handy member functions which can be used in
		// further derived classes
		template 
		struct optional_operations_base : optional_storage_base {
			using optional_storage_base::optional_storage_base;
			void hard_reset() noexcept {
				get().~T();
				this->m_has_value = false;
			}
			template 
			void construct(Args&&... args) noexcept {
				new (std::addressof(this->m_value)) T(std::forward(args)...);
				this->m_has_value = true;
			}
			template 
			void assign(Opt&& rhs) {
				if (this->has_value()) {
					if (rhs.has_value()) {
						this->m_value = std::forward(rhs).get();
					}
					else {
						this->m_value.~T();
						this->m_has_value = false;
					}
				}
				else if (rhs.has_value()) {
					construct(std::forward(rhs).get());
				}
			}
			bool has_value() const {
				return this->m_has_value;
			}
			SOL_TL_OPTIONAL_11_CONSTEXPR T& get() & {
				return this->m_value;
			}
			SOL_TL_OPTIONAL_11_CONSTEXPR const T& get() const& {
				return this->m_value;
			}
			SOL_TL_OPTIONAL_11_CONSTEXPR T&& get() && {
				return std::move(this->m_value);
			}
#ifndef SOL_TL_OPTIONAL_NO_CONSTRR
			constexpr const T&& get() const&& {
				return std::move(this->m_value);
			}
#endif
		};
		// This class manages conditionally having a trivial copy constructor
		// This specialization is for when T is trivially copy constructible
		template 
		struct optional_copy_base : optional_operations_base {
			using optional_operations_base::optional_operations_base;
		};
		// This specialization is for when T is not trivially copy constructible
		template 
		struct optional_copy_base : optional_operations_base {
			using base_t = optional_operations_base;
			using base_t::base_t;
			optional_copy_base() = default;
			optional_copy_base(const optional_copy_base& rhs) : base_t() {
				if (rhs.has_value()) {
					this->construct(rhs.get());
				}
				else {
					this->m_has_value = false;
				}
			}
			optional_copy_base(optional_copy_base&& rhs) = default;
			optional_copy_base& operator=(const optional_copy_base& rhs) = default;
			optional_copy_base& operator=(optional_copy_base&& rhs) = default;
		};
// This class manages conditionally having a trivial move constructor
// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
// doesn't implement an analogue to std::is_trivially_move_constructible. We
// have to make do with a non-trivial move constructor even if T is trivially
// move constructible
#ifndef SOL_TL_OPTIONAL_GCC49
		template ::value>
		struct optional_move_base : optional_copy_base {
			using optional_copy_base::optional_copy_base;
		};
#else
		template 
		struct optional_move_base;
#endif
		template 
		struct optional_move_base : optional_copy_base {
			using optional_copy_base::optional_copy_base;
			optional_move_base() = default;
			optional_move_base(const optional_move_base& rhs) = default;
			optional_move_base(optional_move_base&& rhs) noexcept(std::is_nothrow_move_constructible::value) {
				if (rhs.has_value()) {
					this->construct(std::move(rhs.get()));
				}
				else {
					this->m_has_value = false;
				}
			}
			optional_move_base& operator=(const optional_move_base& rhs) = default;
			optional_move_base& operator=(optional_move_base&& rhs) = default;
		};
		// This class manages conditionally having a trivial copy assignment operator
		template 
		struct optional_copy_assign_base : optional_move_base {
			using optional_move_base::optional_move_base;
		};
		template 
		struct optional_copy_assign_base : optional_move_base {
			using optional_move_base::optional_move_base;
			optional_copy_assign_base() = default;
			optional_copy_assign_base(const optional_copy_assign_base& rhs) = default;
			optional_copy_assign_base(optional_copy_assign_base&& rhs) = default;
			optional_copy_assign_base& operator=(const optional_copy_assign_base& rhs) {
				this->assign(rhs);
				return *this;
			}
			optional_copy_assign_base& operator=(optional_copy_assign_base&& rhs) = default;
		};
// This class manages conditionally having a trivial move assignment operator
// Unfortunately there's no way to achieve this in GCC < 5 AFAIK, since it
// doesn't implement an analogue to std::is_trivially_move_assignable. We have
// to make do with a non-trivial move assignment operator even if T is trivially
// move assignable
#ifndef SOL_TL_OPTIONAL_GCC49
		template ::value&& std::is_trivially_move_constructible::value&& std::is_trivially_move_assignable::value>
		struct optional_move_assign_base : optional_copy_assign_base {
			using optional_copy_assign_base::optional_copy_assign_base;
		};
#else
		template 
		struct optional_move_assign_base;
#endif
		template 
		struct optional_move_assign_base : optional_copy_assign_base {
			using optional_copy_assign_base::optional_copy_assign_base;
			optional_move_assign_base() = default;
			optional_move_assign_base(const optional_move_assign_base& rhs) = default;
			optional_move_assign_base(optional_move_assign_base&& rhs) = default;
			optional_move_assign_base& operator=(const optional_move_assign_base& rhs) = default;
			optional_move_assign_base& operator=(optional_move_assign_base&& rhs) noexcept(
			     std::is_nothrow_move_constructible::value&& std::is_nothrow_move_assignable::value) {
				this->assign(std::move(rhs));
				return *this;
			}
		};
		// optional_delete_ctor_base will conditionally delete copy and move
		// constructors depending on whether T is copy/move constructible
		template ::value, bool EnableMove = std::is_move_constructible::value>
		struct optional_delete_ctor_base {
			optional_delete_ctor_base() = default;
			optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
		};
		template 
		struct optional_delete_ctor_base {
			optional_delete_ctor_base() = default;
			optional_delete_ctor_base(const optional_delete_ctor_base&) = default;
			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
		};
		template 
		struct optional_delete_ctor_base {
			optional_delete_ctor_base() = default;
			optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = default;
			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
		};
		template 
		struct optional_delete_ctor_base {
			optional_delete_ctor_base() = default;
			optional_delete_ctor_base(const optional_delete_ctor_base&) = delete;
			optional_delete_ctor_base(optional_delete_ctor_base&&) noexcept = delete;
			optional_delete_ctor_base& operator=(const optional_delete_ctor_base&) = default;
			optional_delete_ctor_base& operator=(optional_delete_ctor_base&&) noexcept = default;
		};
		// optional_delete_assign_base will conditionally delete copy and move
		// constructors depending on whether T is copy/move constructible + assignable
		template ::value && std::is_copy_assignable::value),
		     bool EnableMove = (std::is_move_constructible::value && std::is_move_assignable::value)>
		struct optional_delete_assign_base {
			optional_delete_assign_base() = default;
			optional_delete_assign_base(const optional_delete_assign_base&) = default;
			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
		};
		template 
		struct optional_delete_assign_base {
			optional_delete_assign_base() = default;
			optional_delete_assign_base(const optional_delete_assign_base&) = default;
			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = default;
			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
		};
		template 
		struct optional_delete_assign_base {
			optional_delete_assign_base() = default;
			optional_delete_assign_base(const optional_delete_assign_base&) = default;
			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = default;
		};
		template 
		struct optional_delete_assign_base {
			optional_delete_assign_base() = default;
			optional_delete_assign_base(const optional_delete_assign_base&) = default;
			optional_delete_assign_base(optional_delete_assign_base&&) noexcept = default;
			optional_delete_assign_base& operator=(const optional_delete_assign_base&) = delete;
			optional_delete_assign_base& operator=(optional_delete_assign_base&&) noexcept = delete;
		};
	} // namespace detail
	/// \brief A tag type to represent an empty optional
	using nullopt_t = std::nullopt_t;
	/// \brief Represents an empty optional
	/// \synopsis static constexpr nullopt_t nullopt;
	///
	/// *Examples*:
	/// ```
	/// sol::optional a = sol::nullopt;
	/// void foo (sol::optional);
	/// foo(sol::nullopt); //pass an empty optional
	/// ```
	using std::nullopt;
	/// @brief An exception for when an optional is accessed through specific methods while it is not engaged.
	class bad_optional_access : public std::exception {
	public:
		/// @brief Default-constructs an optional exception.
		bad_optional_access() = default;
		/// @brief Returns a pointer to a null-terminated string containing the reason for the exception.
		const char* what() const noexcept override {
			return "Optional has no value";
		}
	};
	/// An optional object is an object that contains the storage for another
	/// object and manages the lifetime of this contained object, if any. The
	/// contained object may be initialized after the optional object has been
	/// initialized, and may be destroyed before the optional object has been
	/// destroyed. The initialization state of the contained object is tracked by
	/// the optional object.
	template 
	class optional : private detail::optional_move_assign_base,
	                 private detail::optional_delete_ctor_base,
	                 private detail::optional_delete_assign_base {
		using base = detail::optional_move_assign_base;
		static_assert(!std::is_same::value, "instantiation of optional with in_place_t is ill-formed");
		static_assert(!std::is_same, nullopt_t>::value, "instantiation of optional with nullopt_t is ill-formed");
	public:
// The different versions for C++14 and 11 are needed because deduced return
// types are not SFINAE-safe. This provides better support for things like
// generic lambdas. C.f.
// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0826r0.html
#if defined(SOL_TL_OPTIONAL_CXX14) && !defined(SOL_TL_OPTIONAL_GCC49) && !defined(SOL_TL_OPTIONAL_GCC54) && !defined(SOL_TL_OPTIONAL_GCC55)
		/// \group and_then
		/// Carries out some operation which returns an optional on the stored
		/// object if there is one. \requires `std::invoke(std::forward(f),
		/// value())` returns a `std::optional` for some `U`. \returns Let `U` be
		/// the result of `std::invoke(std::forward