diff --git a/.clang-format b/.clang-format
new file mode 100644
index 0000000..9b3aa8b
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1 @@
+BasedOnStyle: LLVM
diff --git a/optional.hpp b/optional.hpp
index 1088e0f..f134227 100644
--- a/optional.hpp
+++ b/optional.hpp
@@ -7,633 +7,678 @@
// 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 .
+// along with this software. If not, see
+// .
///
+#include
+#include
+#include
#include
#include
-#include
-#include
-#include
namespace tl {
- namespace detail {
- template using remove_cv_t = typename std::remove_cv::type;
- template using remove_const_t = typename std::remove_const::type;
- template using remove_volatile_t = typename std::remove_volatile::type;
- template using add_cv_t = typename std::add_cv::type;
- template using add_const_t = typename std::add_const::type;
- template using add_volatile_t = typename std::add_volatile::type;
- template using remove_reference_t = typename std::remove_reference::type;
- template using add_lvalue_reference_t = typename std::add_lvalue_reference::type;
- template using add_rvalue_reference_t = typename std::add_rvalue_reference::type;
- template using remove_pointer_t = typename std::remove_pointer::type;
- template using add_pointer_t = typename std::add_pointer::type;
- template using make_signed_t = typename std::make_signed::type;
- template using make_unsigned_t = typename std::make_unsigned::type;
- template using remove_extent_t = typename std::remove_extent::type;
- template using remove_all_extents_t = typename std::remove_all_extents::type;
- template using aligned_storage_t = typename std::aligned_storage::type;
- template using aligned_union_t = typename std::aligned_union::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;
- template using common_type_t = typename std::common_type::type;
- template using underlying_type_t = typename std::underlying_type::type;
- template using result_of_t = typename std::result_of::type;
+namespace detail {
+template using remove_cv_t = typename std::remove_cv::type;
+template using remove_const_t = typename std::remove_const::type;
+template
+using remove_volatile_t = typename std::remove_volatile::type;
+template using add_cv_t = typename std::add_cv::type;
+template using add_const_t = typename std::add_const::type;
+template using add_volatile_t = typename std::add_volatile::type;
+template
+using remove_reference_t = typename std::remove_reference::type;
+template
+using add_lvalue_reference_t = typename std::add_lvalue_reference::type;
+template
+using add_rvalue_reference_t = typename std::add_rvalue_reference::type;
+template
+using remove_pointer_t = typename std::remove_pointer::type;
+template using add_pointer_t = typename std::add_pointer::type;
+template using make_signed_t = typename std::make_signed::type;
+template using make_unsigned_t = typename std::make_unsigned::type;
+template using remove_extent_t = typename std::remove_extent::type;
+template
+using remove_all_extents_t = typename std::remove_all_extents::type;
+template
+using aligned_storage_t = typename std::aligned_storage::type;
+template
+using aligned_union_t = typename std::aligned_union::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;
+template
+using common_type_t = typename std::common_type::type;
+template
+using underlying_type_t = typename std::underlying_type::type;
+template using result_of_t = typename std::result_of::type;
- template struct conjunction : std::true_type { };
- template struct conjunction : B { };
- template
- struct conjunction
- : std::conditional, B>::type {};
+template struct conjunction : std::true_type {};
+template struct conjunction : B {};
+template
+struct conjunction
+ : std::conditional, B>::type {};
- template struct voider { using type = void; };
- template using void_t = typename voider::type;
- }
+template struct voider { using type = void; };
+template using void_t = typename voider::type;
+}
- struct in_place_t {
- explicit in_place_t() = default;
- };
- static constexpr in_place_t in_place{};
+struct in_place_t {
+ explicit in_place_t() = default;
+};
+static constexpr in_place_t in_place{};
- // [optional.optional], class template optional
- template
- class optional;
+// [optional.optional], class template optional
+template class optional;
- namespace detail {
- template
- using enable_forward_value = detail::enable_if_t<
- std::is_constructible::value &&
- !std::is_same, in_place_t>::value &&
- !std::is_same, detail::decay_t>::value
- >;
+namespace detail {
+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_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_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
- >;
+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>;
+// 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 {};
- // 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]);
- 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())));
- // 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 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 : std::integral_constant::value &&
- std::is_nothrow_move_assignable::value
- > { };
+template
+struct is_std_swap_noexcept : is_std_swap_noexcept {};
- template
- struct is_std_swap_noexcept : is_std_swap_noexcept { };
+template
+struct is_adl_swap_noexcept
+ : std::integral_constant(0))> {};
+}
- template
- struct is_adl_swap_noexcept : std::integral_constant(0))> { };
- }
+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(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_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<
+ bool,
+ is_swappable::value &&
+ ((decltype(detail::swap_adl_tests::uses_std