diff --git a/Include/auROXTL/ThirdParty/LICENSING.txt b/Include/auROXTL/ThirdParty/LICENSING.txt
new file mode 100644
index 0000000..02c5d3f
--- /dev/null
+++ b/Include/auROXTL/ThirdParty/LICENSING.txt
@@ -0,0 +1 @@
+All software here must be CC0, Unlicense, or similar public domain license.
\ No newline at end of file
diff --git a/Include/auROXTL/ThirdParty/tartanllamaOptional.hpp b/Include/auROXTL/ThirdParty/tartanllamaOptional.hpp
new file mode 100644
index 0000000..ef6a386
--- /dev/null
+++ b/Include/auROXTL/ThirdParty/tartanllamaOptional.hpp
@@ -0,0 +1,3166 @@
+
+///
+// optional - An implementation of std::optional with extensions
+// Written in 2017 by Sy Brand (tartanllama@gmail.com, @TartanLlama)
+//
+// Documentation available at https://tl.tartanllama.xyz/
+//
+// 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 TL_OPTIONAL_HPP
+#define TL_OPTIONAL_HPP
+
+#define TL_OPTIONAL_VERSION_MAJOR 1
+#define TL_OPTIONAL_VERSION_MINOR 1
+#define TL_OPTIONAL_VERSION_PATCH 0
+
+#include
+#include
+#include
+#include
+#include
+
+#if (defined(_MSC_VER) && _MSC_VER == 1900)
+#define TL_OPTIONAL_MSVC2015
+#endif
+
+#if (defined(__GNUC__) && __GNUC__ == 4 && __GNUC_MINOR__ <= 9 && \
+ !defined(__clang__))
+#define TL_OPTIONAL_GCC49
+#endif
+
+#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 4 && \
+ !defined(__clang__))
+#define TL_OPTIONAL_GCC54
+#endif
+
+#if (defined(__GNUC__) && __GNUC__ == 5 && __GNUC_MINOR__ <= 5 && \
+ !defined(__clang__))
+#define 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 TL_OPTIONAL_NO_CONSTRR
+
+// GCC < 5 doesn't support some standard C++11 type traits
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
+ std::has_trivial_copy_constructor::value
+#define 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 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 TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
+#define TL_GCC_LESS_8_TRIVIALLY_COPY_CONSTRUCTIBLE_MUTEX
+namespace tl {
+ 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
+ }
+}
+#endif
+
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
+ tl::detail::is_trivially_copy_constructible::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
+ std::is_trivially_copy_assignable::value
+#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
+#else
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_CONSTRUCTIBLE(T) \
+ std::is_trivially_copy_constructible::value
+#define TL_OPTIONAL_IS_TRIVIALLY_COPY_ASSIGNABLE(T) \
+ std::is_trivially_copy_assignable::value
+#define TL_OPTIONAL_IS_TRIVIALLY_DESTRUCTIBLE(T) std::is_trivially_destructible::value
+#endif
+
+#if __cplusplus > 201103L
+#define TL_OPTIONAL_CXX14
+#endif
+
+// constexpr implies const in C++11, not C++14
+#if (__cplusplus == 201103L || defined(TL_OPTIONAL_MSVC2015) || \
+ defined(TL_OPTIONAL_GCC49))
+#define TL_OPTIONAL_11_CONSTEXPR
+#else
+#define TL_OPTIONAL_11_CONSTEXPR constexpr
+#endif
+
+namespace tl {
+#ifndef TL_MONOSTATE_INPLACE_MUTEX
+#define TL_MONOSTATE_INPLACE_MUTEX
+/// Used to represent an optional with no data; essentially a bool
+ class monostate
+ { };
+
+/// A tag type to tell optional to construct its value in-place
+ struct in_place_t
+ {
+ explicit in_place_t() = default;
+ };
+ /// A tag to tell optional to construct its value in-place
+ static constexpr in_place_t in_place{};
+#endif
+
+ template class optional;
+
+ namespace detail {
+ #ifndef TL_TRAITS_MUTEX
+ #define 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 AuEnableIf::type;
+ template
+ using conditional_t = typename AuConditional::type;
+
+ // std::conjunction from C++17
+ template struct conjunction : AuTrueType
+ { };
+ template struct conjunction : B
+ { };
+ template
+ struct conjunction
+ : AuConditional, B>::type
+ { };
+
+ #if defined(_LIBCPP_VERSION) && __cplusplus == 201103L
+ #define TL_TRAITS_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 TL_TRAITS_LIBCXX_MEM_FN_WORKAROUND
+ template struct is_pointer_to_non_const_member_func : AuFalseType
+ { };
+ template
+ struct is_pointer_to_non_const_member_func : AuTrueType
+ { };
+ template
+ struct is_pointer_to_non_const_member_func : AuTrueType
+ { };
+ template
+ struct is_pointer_to_non_const_member_func : AuTrueType
+ { };
+ template
+ struct is_pointer_to_non_const_member_func : AuTrueType
+ { };
+ template
+ struct is_pointer_to_non_const_member_func : AuTrueType
+ { };
+ template
+ struct is_pointer_to_non_const_member_func : AuTrueType
+ { };
+
+ template struct is_const_or_const_ref : AuFalseType
+ { };
+ template struct is_const_or_const_ref : AuTrueType
+ { };
+ template struct is_const_or_const_ref : AuTrueType
+ { };
+ #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)(AuForward(args)...)))
+ -> decltype(std::mem_fn(f)(AuForward(args)...))
+ {
+ return std::mem_fn(f)(AuForward(args)...);
+ }
+
+ template >::value>>
+ constexpr auto invoke(Fn &&f, Args &&... args) noexcept(
+ noexcept(AuForward(f)(AuForward(args)...)))
+ -> decltype(AuForward(f)(AuForward(args)...))
+ {
+ return AuForward(f)(AuForward(args)...);
+ }
+
+ // std::invoke_result from C++17
+ template struct invoke_result_impl;
+
+ template
+ struct invoke_result_impl<
+ F, decltype(detail::invoke(AuDecalVal(), AuDecalVal()...), void()),
+ Us...>
+ {
+ using type = decltype(detail::invoke(AuDecalVal(), AuDecalVal()...));
+ };
+
+ template
+ using invoke_result = invoke_result_impl;
+
+ template
+ using invoke_result_t = typename invoke_result::type;
+
+ #if defined(_MSC_VER) && _MSC_VER <= 1900
+ // TODO make a version which works with MSVC 2015
+ template struct is_swappable : AuTrueType
+ { };
+
+ template struct is_nothrow_swappable : AuTrueType
+ { };
+ #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 AuFalseType can_swap(...) noexcept(false);
+ template (), AuDecalVal()))>
+ AuTrueType can_swap(int) noexcept(noexcept(swap(AuDecalVal(),
+ AuDecalVal())));
+
+ template AuFalseType uses_std(...);
+ template
+ std::is_same(), AuDecalVal())), 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<
+ bool,
+ decltype(detail::swap_adl_tests::can_swap(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<
+ bool,
+ decltype(detail::swap_adl_tests::can_swap(0))::value &&
+ (!decltype(
+ detail::swap_adl_tests::uses_std(0))::value ||
+ is_swappable::value)>
+ { };
+
+ template
+ struct is_nothrow_swappable
+ : std::integral_constant<
+ bool,
+ is_swappable::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
+ #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 tl::optional
+ template struct is_optional_impl : AuFalseType
+ { };
+ template struct is_optional_impl> : AuTrueType
+ { };
+ template using is_optional = is_optional_impl>;
+
+ // Change void to tl::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<
+ std::is_constructible::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<
+ !std::is_same, 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<
+ std::is_constructible::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>;
+
+ // The storage base manages the actual storage, and correctly propagates
+ // trivial destruction from T. This case is for when T is not trivially
+ // destructible.
+ template ::value>
+ struct optional_storage_base
+ {
+ TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
+ : m_dummy(), m_has_value(false)
+ { }
+
+ template
+ TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
+ : m_value(AuForward(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
+ {
+ TL_OPTIONAL_11_CONSTEXPR optional_storage_base() noexcept
+ : m_dummy(), m_has_value(false)
+ { }
+
+ template
+ TL_OPTIONAL_11_CONSTEXPR optional_storage_base(in_place_t, U &&... u)
+ : m_value(AuForward(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)
+ {
+ new (std::addressof(this->m_value)) T(AuForward(args)...);
+ this->m_has_value = true;
+ }
+
+ template void assign(Opt &&rhs)
+ {
+ if (this->has_value())
+ {
+ if (rhs.has_value())
+ {
+ this->m_value = AuForward(rhs).get();
+ }
+ else
+ {
+ this->m_value.~T();
+ this->m_has_value = false;
+ }
+ }
+
+ else if (rhs.has_value())
+ {
+ construct(AuForward(rhs).get());
+ }
+ }
+
+ bool has_value() const
+ {
+ return this->m_has_value;
+ }
+
+ TL_OPTIONAL_11_CONSTEXPR T &get() &
+ {
+ return this->m_value;
+ }
+ TL_OPTIONAL_11_CONSTEXPR const T &get() const &
+ {
+ return this->m_value;
+ }
+ TL_OPTIONAL_11_CONSTEXPR T &&get() &&
+ {
+ return AuMove(this->m_value);
+ }
+ #ifndef TL_OPTIONAL_NO_CONSTRR
+ constexpr const T &&get() const &&
+ {
+ return AuMove(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 optional_operations_base::optional_operations_base;
+
+ optional_copy_base() = default;
+ optional_copy_base(const optional_copy_base &rhs)
+ : optional_operations_base()
+ {
+ 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 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(AuMove(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 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(AuMove(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
+
+ /// A tag type to represent an empty optional
+ struct nullopt_t
+ {
+ struct do_not_use
+ { };
+ constexpr explicit nullopt_t(do_not_use, do_not_use) noexcept
+ { }
+ };
+ /// Represents an empty optional
+ static constexpr nullopt_t nullopt{nullopt_t::do_not_use{},
+ nullopt_t::do_not_use{}};
+
+ class bad_optional_access : public std::exception
+ {
+ public:
+ bad_optional_access() = default;
+ const char *what() const noexcept
+ {
+ 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(TL_OPTIONAL_CXX14) && !defined(TL_OPTIONAL_GCC49) && \
+ !defined(TL_OPTIONAL_GCC54) && !defined(TL_OPTIONAL_GCC55)
+ /// Carries out some operation which returns an optional on the stored
+ /// object if there is one.
+ template TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) &
+ {
+ using result = detail::invoke_result_t;
+ static_assert(detail::is_optional::value,
+ "F must return an optional");
+
+ return has_value() ? detail::invoke(AuForward(f), **this)
+ : result(nullopt);
+ }
+
+ template TL_OPTIONAL_11_CONSTEXPR auto and_then(F &&f) &&
+ {
+ using result = detail::invoke_result_t;
+ static_assert(detail::is_optional