diff --git a/README.md b/README.md
index 230bbf3b6e..4ca83e9b6a 100644
--- a/README.md
+++ b/README.md
@@ -207,6 +207,9 @@ See the comments in the source files in `src/3rdparty/md5` for the complete lice
The implementations of Posix `getaddrinfo` and `getnameinfo` for OS/2 in `src/3rdparty/os2` are distributed partly under the GNU Lesser General Public License 2.1, and partly under the (3-clause) BSD license.
The exact licensing terms can be found in `src/3rdparty/os2/getaddrinfo.c` resp. `src/3rdparty/os2/getnameinfo.c`.
+The implementation of C++17 `std::optional` in `src/3rdparty/optional` is licensed under the Boost Software License - Version 1.0.
+See `src/3rdparty/optional/LICENSE_1_0.txt` for the complete license text.
+
## 4.0 Credits
diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj
index 6453d62b86..4e7f7b7c8d 100644
--- a/projects/openttd_vs140.vcxproj
+++ b/projects/openttd_vs140.vcxproj
@@ -974,6 +974,8 @@
+
+
diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters
index 0405740d4c..fd5c07157c 100644
--- a/projects/openttd_vs140.vcxproj.filters
+++ b/projects/openttd_vs140.vcxproj.filters
@@ -28,78 +28,81 @@
{c76ff9f1-1e62-46d8-8d55-000000000008}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000009}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000010}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000011}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000012}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000013}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000014}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000015}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000016}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000017}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000018}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000019}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000020}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000021}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000022}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000023}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000024}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000025}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000026}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000027}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000028}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000029}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000030}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000031}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000032}
+
+ {c76ff9f1-1e62-46d8-8d55-000000000033}
+
@@ -2010,6 +2013,12 @@
MD5
+
+ Compat
+
+
+ Compat
+
Script
diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj
index ecfed4a038..4ab1ad85df 100644
--- a/projects/openttd_vs141.vcxproj
+++ b/projects/openttd_vs141.vcxproj
@@ -974,6 +974,8 @@
+
+
diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters
index 0405740d4c..fd5c07157c 100644
--- a/projects/openttd_vs141.vcxproj.filters
+++ b/projects/openttd_vs141.vcxproj.filters
@@ -28,78 +28,81 @@
{c76ff9f1-1e62-46d8-8d55-000000000008}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000009}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000010}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000011}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000012}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000013}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000014}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000015}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000016}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000017}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000018}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000019}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000020}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000021}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000022}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000023}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000024}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000025}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000026}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000027}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000028}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000029}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000030}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000031}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000032}
+
+ {c76ff9f1-1e62-46d8-8d55-000000000033}
+
@@ -2010,6 +2013,12 @@
MD5
+
+ Compat
+
+
+ Compat
+
Script
diff --git a/projects/openttd_vs142.vcxproj b/projects/openttd_vs142.vcxproj
index 49858a3e1d..2539fe1d5f 100644
--- a/projects/openttd_vs142.vcxproj
+++ b/projects/openttd_vs142.vcxproj
@@ -100,7 +100,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Full
AnySuitable
true
@@ -168,7 +168,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
@@ -223,7 +223,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Full
AnySuitable
true
@@ -289,7 +289,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
@@ -974,6 +974,8 @@
+
+
diff --git a/projects/openttd_vs142.vcxproj.filters b/projects/openttd_vs142.vcxproj.filters
index 0405740d4c..fd5c07157c 100644
--- a/projects/openttd_vs142.vcxproj.filters
+++ b/projects/openttd_vs142.vcxproj.filters
@@ -28,78 +28,81 @@
{c76ff9f1-1e62-46d8-8d55-000000000008}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000009}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000010}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000011}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000012}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000013}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000014}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000015}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000016}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000017}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000018}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000019}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000020}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000021}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000022}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000023}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000024}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000025}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000026}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000027}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000028}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000029}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000030}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000031}
-
+
{c76ff9f1-1e62-46d8-8d55-000000000032}
+
+ {c76ff9f1-1e62-46d8-8d55-000000000033}
+
@@ -2010,6 +2013,12 @@
MD5
+
+ Compat
+
+
+ Compat
+
Script
diff --git a/projects/openttd_vs142.vcxproj.in b/projects/openttd_vs142.vcxproj.in
index 83befcd8d0..6941b3450b 100644
--- a/projects/openttd_vs142.vcxproj.in
+++ b/projects/openttd_vs142.vcxproj.in
@@ -100,7 +100,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Full
AnySuitable
true
@@ -168,7 +168,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
@@ -223,7 +223,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Full
AnySuitable
true
@@ -289,7 +289,7 @@
- /J /Zc:throwingNew /std:c++latest %(AdditionalOptions)
+ /J /Zc:throwingNew /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
Disabled
true
..\objs\langs;..\objs\settings;..\src\3rdparty\squirrel\include;%(AdditionalIncludeDirectories)
diff --git a/projects/settingsgen_vs142.vcxproj b/projects/settingsgen_vs142.vcxproj
index 23a4e18562..fb2f7a731e 100644
--- a/projects/settingsgen_vs142.vcxproj
+++ b/projects/settingsgen_vs142.vcxproj
@@ -39,6 +39,7 @@
%(Inputs)
+ /std:c++latest /Zc:__cplusplus %(AdditionalOptions)
MinSpace
Size
SETTINGSGEN;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
diff --git a/source.list b/source.list
index ce3c50729a..cc9d10c998 100644
--- a/source.list
+++ b/source.list
@@ -691,6 +691,10 @@ table/water_land.h
3rdparty/md5/md5.cpp
3rdparty/md5/md5.h
+# Compat
+3rdparty/optional/optional.hpp
+3rdparty/optional/ottd_optional.h
+
# Script
script/script_config.cpp
script/script_config.hpp
diff --git a/src/3rdparty/optional/LICENSE_1_0.txt b/src/3rdparty/optional/LICENSE_1_0.txt
new file mode 100644
index 0000000000..36b7cd93cd
--- /dev/null
+++ b/src/3rdparty/optional/LICENSE_1_0.txt
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/src/3rdparty/optional/optional.hpp b/src/3rdparty/optional/optional.hpp
new file mode 100644
index 0000000000..fe1832b2ae
--- /dev/null
+++ b/src/3rdparty/optional/optional.hpp
@@ -0,0 +1,1066 @@
+// Copyright (C) 2011 - 2012 Andrzej Krzemienski.
+//
+// Use, modification, and distribution is subject to the Boost Software
+// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// The idea and interface is based on Boost.Optional library
+// authored by Fernando Luis Cacciola Carballal
+
+# ifndef ___OPTIONAL_HPP___
+# define ___OPTIONAL_HPP___
+
+# include
+# include
+# include
+# include
+# include
+# include
+# include
+
+# define TR2_OPTIONAL_REQUIRES(...) typename enable_if<__VA_ARGS__::value, bool>::type = false
+
+# if defined __GNUC__ // NOTE: GNUC is also defined for Clang
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+# endif
+#
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)
+# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_7_AND_HIGHER___
+# endif
+#
+# if (__GNUC__ == 4) && (__GNUC_MINOR__ == 8) && (__GNUC_PATCHLEVEL__ >= 1)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# elif (__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# elif (__GNUC__ > 4)
+# define TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# endif
+# endif
+#
+# if defined __clang_major__
+# if (__clang_major__ == 3 && __clang_minor__ >= 5)
+# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# elif (__clang_major__ > 3)
+# define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# endif
+# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
+# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+# elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
+# define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+# endif
+# endif
+#
+# if defined _MSC_VER
+# if (_MSC_VER >= 1900)
+# define TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+# endif
+# endif
+
+# if defined __clang__
+# if (__clang_major__ > 2) || (__clang_major__ == 2) && (__clang_minor__ >= 9)
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# else
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+# endif
+# elif defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 1
+# else
+# define OPTIONAL_HAS_THIS_RVALUE_REFS 0
+# endif
+
+
+# if defined TR2_OPTIONAL_GCC_4_8_1_AND_HIGHER___
+# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 1
+# define OPTIONAL_CONSTEXPR_INIT_LIST constexpr
+# else
+# define OPTIONAL_HAS_CONSTEXPR_INIT_LIST 0
+# define OPTIONAL_CONSTEXPR_INIT_LIST
+# endif
+
+# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)
+# define OPTIONAL_HAS_MOVE_ACCESSORS 1
+# else
+# define OPTIONAL_HAS_MOVE_ACCESSORS 0
+# endif
+
+# // In C++11 constexpr implies const, so we need to make non-const members also non-constexpr
+# if (defined __cplusplus) && (__cplusplus == 201103L)
+# define OPTIONAL_MUTABLE_CONSTEXPR
+# else
+# define OPTIONAL_MUTABLE_CONSTEXPR constexpr
+# endif
+
+namespace std{
+
+namespace experimental{
+
+// BEGIN workaround for missing is_trivially_destructible
+# if defined TR2_OPTIONAL_GCC_4_8_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+ // leave it: the user doesn't want it
+# else
+ template
+ using is_trivially_destructible = std::has_trivial_destructor;
+# endif
+// END workaround for missing is_trivially_destructible
+
+# if (defined TR2_OPTIONAL_GCC_4_7_AND_HIGHER___)
+ // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
+ // leave it; our metafunctions are already defined.
+# elif defined TR2_OPTIONAL_MSVC_2015_AND_HIGHER___
+ // leave it: it is already there
+# elif defined TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS
+ // leave it: the user doesn't want it
+# else
+
+
+// workaround for missing traits in GCC and CLANG
+template
+struct is_nothrow_move_constructible
+{
+ constexpr static bool value = std::is_nothrow_constructible::value;
+};
+
+
+template
+struct is_assignable
+{
+ template
+ constexpr static bool has_assign(...) { return false; }
+
+ template () = std::declval(), true)) >
+ // the comma operator is necessary for the cases where operator= returns void
+ constexpr static bool has_assign(bool) { return true; }
+
+ constexpr static bool value = has_assign(true);
+};
+
+
+template
+struct is_nothrow_move_assignable
+{
+ template
+ struct has_nothrow_move_assign {
+ constexpr static bool value = false;
+ };
+
+ template
+ struct has_nothrow_move_assign {
+ constexpr static bool value = noexcept( std::declval() = std::declval() );
+ };
+
+ constexpr static bool value = has_nothrow_move_assign::value>::value;
+};
+// end workaround
+
+
+# endif
+
+
+
+// 20.5.4, optional for object types
+template class optional;
+
+// 20.5.5, optional for lvalue reference types
+template class optional;
+
+
+// workaround: std utility functions aren't constexpr yet
+template inline constexpr T&& constexpr_forward(typename std::remove_reference::type& t) noexcept
+{
+ return static_cast(t);
+}
+
+template inline constexpr T&& constexpr_forward(typename std::remove_reference::type&& t) noexcept
+{
+ static_assert(!std::is_lvalue_reference::value, "!!");
+ return static_cast(t);
+}
+
+template inline constexpr typename std::remove_reference::type&& constexpr_move(T&& t) noexcept
+{
+ return static_cast::type&&>(t);
+}
+
+
+#if defined NDEBUG
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) (EXPR)
+#else
+# define TR2_OPTIONAL_ASSERTED_EXPRESSION(CHECK, EXPR) ((CHECK) ? (EXPR) : ([]{assert(!#CHECK);}(), (EXPR)))
+#endif
+
+
+namespace detail_
+{
+
+// static_addressof: a constexpr version of addressof
+template
+struct has_overloaded_addressof
+{
+ template
+ constexpr static bool has_overload(...) { return false; }
+
+ template ().operator&()) >
+ constexpr static bool has_overload(bool) { return true; }
+
+ constexpr static bool value = has_overload(true);
+};
+
+template )>
+constexpr T* static_addressof(T& ref)
+{
+ return &ref;
+}
+
+template )>
+T* static_addressof(T& ref)
+{
+ return std::addressof(ref);
+}
+
+
+// the call to convert(b) has return type A and converts b to type A iff b decltype(b) is implicitly convertible to A
+template
+constexpr U convert(U v) { return v; }
+
+
+namespace swap_ns
+{
+ using std::swap;
+
+ template
+ void adl_swap(T& t, T& u) noexcept(noexcept(swap(t, u)))
+ {
+ swap(t, u);
+ }
+
+} // namespace swap_ns
+
+} // namespace detail
+
+
+constexpr struct trivial_init_t{} trivial_init{};
+
+
+// 20.5.6, In-place construction
+constexpr struct in_place_t{} in_place{};
+
+
+// 20.5.7, Disengaged state indicator
+struct nullopt_t
+{
+ struct init{};
+ constexpr explicit nullopt_t(init){}
+};
+constexpr nullopt_t nullopt{nullopt_t::init()};
+
+
+// 20.5.8, class bad_optional_access
+class bad_optional_access : public logic_error {
+public:
+ explicit bad_optional_access(const string& what_arg) : logic_error{what_arg} {}
+ explicit bad_optional_access(const char* what_arg) : logic_error{what_arg} {}
+};
+
+
+template
+union storage_t
+{
+ unsigned char dummy_;
+ T value_;
+
+ constexpr storage_t( trivial_init_t ) noexcept : dummy_() {};
+
+ template
+ constexpr storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {}
+
+ ~storage_t(){}
+};
+
+
+template
+union constexpr_storage_t
+{
+ unsigned char dummy_;
+ T value_;
+
+ constexpr constexpr_storage_t( trivial_init_t ) noexcept : dummy_() {};
+
+ template
+ constexpr constexpr_storage_t( Args&&... args ) : value_(constexpr_forward(args)...) {}
+
+ ~constexpr_storage_t() = default;
+};
+
+
+template
+struct optional_base
+{
+ bool init_;
+ storage_t storage_;
+
+ constexpr optional_base() noexcept : init_(false), storage_(trivial_init) {};
+
+ explicit constexpr optional_base(const T& v) : init_(true), storage_(v) {}
+
+ explicit constexpr optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
+
+ template explicit optional_base(in_place_t, Args&&... args)
+ : init_(true), storage_(constexpr_forward(args)...) {}
+
+ template >)>
+ explicit optional_base(in_place_t, std::initializer_list il, Args&&... args)
+ : init_(true), storage_(il, std::forward(args)...) {}
+
+ ~optional_base() { if (init_) storage_.value_.T::~T(); }
+};
+
+
+template
+struct constexpr_optional_base
+{
+ bool init_;
+ constexpr_storage_t storage_;
+
+ constexpr constexpr_optional_base() noexcept : init_(false), storage_(trivial_init) {};
+
+ explicit constexpr constexpr_optional_base(const T& v) : init_(true), storage_(v) {}
+
+ explicit constexpr constexpr_optional_base(T&& v) : init_(true), storage_(constexpr_move(v)) {}
+
+ template explicit constexpr constexpr_optional_base(in_place_t, Args&&... args)
+ : init_(true), storage_(constexpr_forward(args)...) {}
+
+ template >)>
+ OPTIONAL_CONSTEXPR_INIT_LIST explicit constexpr_optional_base(in_place_t, std::initializer_list il, Args&&... args)
+ : init_(true), storage_(il, std::forward(args)...) {}
+
+ ~constexpr_optional_base() = default;
+};
+
+template
+using OptionalBase = typename std::conditional<
+ is_trivially_destructible::value, // if possible
+ constexpr_optional_base::type>, // use base with trivial destructor
+ optional_base::type>
+>::type;
+
+
+
+template
+class optional : private OptionalBase
+{
+ static_assert( !std::is_same::type, nullopt_t>::value, "bad T" );
+ static_assert( !std::is_same::type, in_place_t>::value, "bad T" );
+
+
+ constexpr bool initialized() const noexcept { return OptionalBase::init_; }
+ typename std::remove_const::type* dataptr() { return std::addressof(OptionalBase::storage_.value_); }
+ constexpr const T* dataptr() const { return detail_::static_addressof(OptionalBase::storage_.value_); }
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+ constexpr const T& contained_val() const& { return OptionalBase::storage_.value_; }
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+ OPTIONAL_MUTABLE_CONSTEXPR T&& contained_val() && { return std::move(OptionalBase::storage_.value_); }
+ OPTIONAL_MUTABLE_CONSTEXPR T& contained_val() & { return OptionalBase::storage_.value_; }
+# else
+ T& contained_val() & { return OptionalBase::storage_.value_; }
+ T&& contained_val() && { return std::move(OptionalBase::storage_.value_); }
+# endif
+# else
+ constexpr const T& contained_val() const { return OptionalBase::storage_.value_; }
+ T& contained_val() { return OptionalBase::storage_.value_; }
+# endif
+
+ void clear() noexcept {
+ if (initialized()) dataptr()->T::~T();
+ OptionalBase::init_ = false;
+ }
+
+ template
+ void initialize(Args&&... args) noexcept(noexcept(T(std::forward(args)...)))
+ {
+ assert(!OptionalBase::init_);
+ ::new (static_cast(dataptr())) T(std::forward(args)...);
+ OptionalBase::init_ = true;
+ }
+
+ template
+ void initialize(std::initializer_list il, Args&&... args) noexcept(noexcept(T(il, std::forward(args)...)))
+ {
+ assert(!OptionalBase::init_);
+ ::new (static_cast(dataptr())) T(il, std::forward(args)...);
+ OptionalBase::init_ = true;
+ }
+
+public:
+ typedef T value_type;
+
+ // 20.5.5.1, constructors
+ constexpr optional() noexcept : OptionalBase() {};
+ constexpr optional(nullopt_t) noexcept : OptionalBase() {};
+
+ optional(const optional& rhs)
+ : OptionalBase()
+ {
+ if (rhs.initialized()) {
+ ::new (static_cast(dataptr())) T(*rhs);
+ OptionalBase::init_ = true;
+ }
+ }
+
+ optional(optional&& rhs) noexcept(is_nothrow_move_constructible::value)
+ : OptionalBase()
+ {
+ if (rhs.initialized()) {
+ ::new (static_cast(dataptr())) T(std::move(*rhs));
+ OptionalBase::init_ = true;
+ }
+ }
+
+ constexpr optional(const T& v) : OptionalBase(v) {}
+
+ constexpr optional(T&& v) : OptionalBase(constexpr_move(v)) {}
+
+ template
+ explicit constexpr optional(in_place_t, Args&&... args)
+ : OptionalBase(in_place_t{}, constexpr_forward(args)...) {}
+
+ template >)>
+ OPTIONAL_CONSTEXPR_INIT_LIST explicit optional(in_place_t, std::initializer_list il, Args&&... args)
+ : OptionalBase(in_place_t{}, il, constexpr_forward(args)...) {}
+
+ // 20.5.4.2, Destructor
+ ~optional() = default;
+
+ // 20.5.4.3, assignment
+ optional& operator=(nullopt_t) noexcept
+ {
+ clear();
+ return *this;
+ }
+
+ optional& operator=(const optional& rhs)
+ {
+ if (initialized() == true && rhs.initialized() == false) clear();
+ else if (initialized() == false && rhs.initialized() == true) initialize(*rhs);
+ else if (initialized() == true && rhs.initialized() == true) contained_val() = *rhs;
+ return *this;
+ }
+
+ optional& operator=(optional&& rhs)
+ noexcept(is_nothrow_move_assignable::value && is_nothrow_move_constructible::value)
+ {
+ if (initialized() == true && rhs.initialized() == false) clear();
+ else if (initialized() == false && rhs.initialized() == true) initialize(std::move(*rhs));
+ else if (initialized() == true && rhs.initialized() == true) contained_val() = std::move(*rhs);
+ return *this;
+ }
+
+ template
+ auto operator=(U&& v)
+ -> typename enable_if
+ <
+ is_same::type, T>::value,
+ optional&
+ >::type
+ {
+ if (initialized()) { contained_val() = std::forward(v); }
+ else { initialize(std::forward(v)); }
+ return *this;
+ }
+
+
+ template
+ void emplace(Args&&... args)
+ {
+ clear();
+ initialize(std::forward(args)...);
+ }
+
+ template
+ void emplace(initializer_list il, Args&&... args)
+ {
+ clear();
+ initialize(il, std::forward(args)...);
+ }
+
+ // 20.5.4.4, Swap
+ void swap(optional& rhs) noexcept(is_nothrow_move_constructible::value
+ && noexcept(detail_::swap_ns::adl_swap(declval(), declval())))
+ {
+ if (initialized() == true && rhs.initialized() == false) { rhs.initialize(std::move(**this)); clear(); }
+ else if (initialized() == false && rhs.initialized() == true) { initialize(std::move(*rhs)); rhs.clear(); }
+ else if (initialized() == true && rhs.initialized() == true) { using std::swap; swap(**this, *rhs); }
+ }
+
+ // 20.5.4.5, Observers
+
+ explicit constexpr operator bool() const noexcept { return initialized(); }
+ constexpr bool has_value() const noexcept { return initialized(); }
+
+ constexpr T const* operator ->() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), dataptr());
+ }
+
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+ OPTIONAL_MUTABLE_CONSTEXPR T* operator ->() {
+ assert (initialized());
+ return dataptr();
+ }
+
+ constexpr T const& operator *() const& {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T& operator *() & {
+ assert (initialized());
+ return contained_val();
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T&& operator *() && {
+ assert (initialized());
+ return constexpr_move(contained_val());
+ }
+
+ constexpr T const& value() const& {
+ return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T& value() & {
+ return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+ }
+
+ OPTIONAL_MUTABLE_CONSTEXPR T&& value() && {
+ if (!initialized()) throw bad_optional_access("bad optional access");
+ return std::move(contained_val());
+ }
+
+# else
+
+ T* operator ->() {
+ assert (initialized());
+ return dataptr();
+ }
+
+ constexpr T const& operator *() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(initialized(), contained_val());
+ }
+
+ T& operator *() {
+ assert (initialized());
+ return contained_val();
+ }
+
+ constexpr T const& value() const {
+ return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+ }
+
+ T& value() {
+ return initialized() ? contained_val() : (throw bad_optional_access("bad optional access"), contained_val());
+ }
+
+# endif
+
+# if OPTIONAL_HAS_THIS_RVALUE_REFS == 1
+
+ template
+ constexpr T value_or(V&& v) const&
+ {
+ return *this ? **this : detail_::convert(constexpr_forward(v));
+ }
+
+# if OPTIONAL_HAS_MOVE_ACCESSORS == 1
+
+ template
+ OPTIONAL_MUTABLE_CONSTEXPR T value_or(V&& v) &&
+ {
+ return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v));
+ }
+
+# else
+
+ template
+ T value_or(V&& v) &&
+ {
+ return *this ? constexpr_move(const_cast&>(*this).contained_val()) : detail_::convert(constexpr_forward(v));
+ }
+
+# endif
+
+# else
+
+ template
+ constexpr T value_or(V&& v) const
+ {
+ return *this ? **this : detail_::convert(constexpr_forward(v));
+ }
+
+# endif
+
+ // 20.6.3.6, modifiers
+ void reset() noexcept { clear(); }
+};
+
+
+template
+class optional
+{
+ static_assert( !std::is_same::value, "bad T" );
+ static_assert( !std::is_same::value, "bad T" );
+ T* ref;
+
+public:
+
+ // 20.5.5.1, construction/destruction
+ constexpr optional() noexcept : ref(nullptr) {}
+
+ constexpr optional(nullopt_t) noexcept : ref(nullptr) {}
+
+ constexpr optional(T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+ optional(T&&) = delete;
+
+ constexpr optional(const optional& rhs) noexcept : ref(rhs.ref) {}
+
+ explicit constexpr optional(in_place_t, T& v) noexcept : ref(detail_::static_addressof(v)) {}
+
+ explicit optional(in_place_t, T&&) = delete;
+
+ ~optional() = default;
+
+ // 20.5.5.2, mutation
+ optional& operator=(nullopt_t) noexcept {
+ ref = nullptr;
+ return *this;
+ }
+
+ // optional& operator=(const optional& rhs) noexcept {
+ // ref = rhs.ref;
+ // return *this;
+ // }
+
+ // optional& operator=(optional&& rhs) noexcept {
+ // ref = rhs.ref;
+ // return *this;
+ // }
+
+ template
+ auto operator=(U&& rhs) noexcept
+ -> typename enable_if
+ <
+ is_same::type, optional>::value,
+ optional&
+ >::type
+ {
+ ref = rhs.ref;
+ return *this;
+ }
+
+ template
+ auto operator=(U&& rhs) noexcept
+ -> typename enable_if
+ <
+ !is_same::type, optional>::value,
+ optional&
+ >::type
+ = delete;
+
+ void emplace(T& v) noexcept {
+ ref = detail_::static_addressof(v);
+ }
+
+ void emplace(T&&) = delete;
+
+
+ void swap(optional& rhs) noexcept
+ {
+ std::swap(ref, rhs.ref);
+ }
+
+ // 20.5.5.3, observers
+ constexpr T* operator->() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, ref);
+ }
+
+ constexpr T& operator*() const {
+ return TR2_OPTIONAL_ASSERTED_EXPRESSION(ref, *ref);
+ }
+
+ constexpr T& value() const {
+ return ref ? *ref : (throw bad_optional_access("bad optional access"), *ref);
+ }
+
+ explicit constexpr operator bool() const noexcept {
+ return ref != nullptr;
+ }
+
+ constexpr bool has_value() const noexcept {
+ return ref != nullptr;
+ }
+
+ template
+ constexpr typename decay::type value_or(V&& v) const
+ {
+ return *this ? **this : detail_::convert::type>(constexpr_forward(v));
+ }
+
+ // x.x.x.x, modifiers
+ void reset() noexcept { ref = nullptr; }
+};
+
+
+template
+class optional
+{
+ static_assert( sizeof(T) == 0, "optional rvalue references disallowed" );
+};
+
+
+// 20.5.8, Relational operators
+template constexpr bool operator==(const optional& x, const optional& y)
+{
+ return bool(x) != bool(y) ? false : bool(x) == false ? true : *x == *y;
+}
+
+template constexpr bool operator!=(const optional& x, const optional& y)
+{
+ return !(x == y);
+}
+
+template constexpr bool operator<(const optional& x, const optional& y)
+{
+ return (!y) ? false : (!x) ? true : *x < *y;
+}
+
+template constexpr bool operator>(const optional& x, const optional& y)
+{
+ return (y < x);
+}
+
+template constexpr bool operator<=(const optional& x, const optional& y)
+{
+ return !(y < x);
+}
+
+template constexpr bool operator>=(const optional& x, const optional& y)
+{
+ return !(x < y);
+}
+
+
+// 20.5.9, Comparison with nullopt
+template constexpr bool operator==(const optional& x, nullopt_t) noexcept
+{
+ return (!x);
+}
+
+template constexpr bool operator==(nullopt_t, const optional& x) noexcept
+{
+ return (!x);
+}
+
+template constexpr bool operator!=(const optional& x, nullopt_t) noexcept
+{
+ return bool(x);
+}
+
+template constexpr bool operator!=(nullopt_t, const optional& x) noexcept
+{
+ return bool(x);
+}
+
+template constexpr bool operator<(const optional&, nullopt_t) noexcept
+{
+ return false;
+}
+
+template constexpr bool operator<(nullopt_t, const optional& x) noexcept
+{
+ return bool(x);
+}
+
+template constexpr bool operator<=(const optional& x, nullopt_t) noexcept
+{
+ return (!x);
+}
+
+template constexpr bool operator<=(nullopt_t, const optional&) noexcept
+{
+ return true;
+}
+
+template constexpr bool operator>(const optional& x, nullopt_t) noexcept
+{
+ return bool(x);
+}
+
+template constexpr bool operator>(nullopt_t, const optional&) noexcept
+{
+ return false;
+}
+
+template constexpr bool operator>=(const optional&, nullopt_t) noexcept
+{
+ return true;
+}
+
+template constexpr bool operator>=(nullopt_t, const optional& x) noexcept
+{
+ return (!x);
+}
+
+
+
+// 20.5.10, Comparison with T
+template constexpr bool operator==(const optional& x, const T& v)
+{
+ return bool(x) ? *x == v : false;
+}
+
+template constexpr bool operator==(const T& v, const optional& x)
+{
+ return bool(x) ? v == *x : false;
+}
+
+template constexpr bool operator!=(const optional& x, const T& v)
+{
+ return bool(x) ? *x != v : true;
+}
+
+template constexpr bool operator!=(const T& v, const optional& x)
+{
+ return bool(x) ? v != *x : true;
+}
+
+template constexpr bool operator<(const optional& x, const T& v)
+{
+ return bool(x) ? *x < v : true;
+}
+
+template constexpr bool operator>(const T& v, const optional& x)
+{
+ return bool(x) ? v > *x : true;
+}
+
+template constexpr bool operator>(const optional& x, const T& v)
+{
+ return bool(x) ? *x > v : false;
+}
+
+template constexpr bool operator<(const T& v, const optional& x)
+{
+ return bool(x) ? v < *x : false;
+}
+
+template constexpr bool operator>=(const optional& x, const T& v)
+{
+ return bool(x) ? *x >= v : false;
+}
+
+template