diff --git a/src/ltpl/tuple.hpp b/src/ltpl/tuple.hpp index 4ed6295..1d3e05c 100644 --- a/src/ltpl/tuple.hpp +++ b/src/ltpl/tuple.hpp @@ -237,21 +237,6 @@ constexpr decltype(auto) get(ltpl::Tuple& tuple) noexcept }(std::make_index_sequence{}); } -constexpr bool all_true(Access) noexcept { return true; } - -template -constexpr bool all_true(bool const (&array)[N]) noexcept -{ - for (bool ok : array) - { - if (!ok) - { - return false; - } - } - return true; -} - struct TupleCatIndex { std::size_t outer; @@ -276,8 +261,8 @@ class Tuple ~Tuple() = default; // Non-empty Tuple, default construct all elements. - constexpr Tuple() // - noexcept(detail::all_true({detail::NothrowDefaultAndMoveConstructible...})) // + constexpr Tuple() // + noexcept((detail::NothrowDefaultAndMoveConstructible && ... && true)) // requires(sizeof...(T) > 0) : lambda(detail::make_lambda(T()...)) { @@ -290,21 +275,21 @@ class Tuple // If every element of the Tuple can be implicitly constructed from the arguments then this constructor is also // implicit. template - constexpr explicit(!detail::all_true({std::is_convertible_v...})) // - Tuple(U&&... v) // - noexcept(detail::all_true({std::is_nothrow_constructible_v...})) // - requires(sizeof...(T) == sizeof...(U) && sizeof...(T) >= 1 && - detail::all_true({std::is_constructible_v...}) && detail::is_not_exactly_v) + constexpr explicit((!std::is_convertible_v || ... || false)) // + Tuple(U&&... v) // + noexcept((std::is_nothrow_constructible_v && ... && true)) // + requires(sizeof...(T) == sizeof...(U) && sizeof...(T) >= 1 && (std::is_constructible_v && ... && true) && + detail::is_not_exactly_v) : lambda(detail::make_lambda(detail::Wrap::wrap(static_cast(v))...)) { } // Converting copy constructor template - constexpr explicit(!detail::all_true({std::is_convertible_v...})) // - Tuple(const Tuple& other) // - noexcept(detail::all_true({std::is_nothrow_constructible_v...})) // - requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_constructible_v...}) && + constexpr explicit((!std::is_convertible_v || ... || false)) // + Tuple(const Tuple& other) // + noexcept((std::is_nothrow_constructible_v && ... && true)) // + requires(sizeof...(T) == sizeof...(U) && (std::is_constructible_v && ... && true) && detail::is_converting_copy_constructor_v) // We have to const_cast because the lambda's operator() is mutable. But since we cast each element to const& no // UB can occur. @@ -318,10 +303,10 @@ class Tuple // Converting move constructor template - constexpr explicit(!detail::all_true({std::is_convertible_v...})) // - Tuple(Tuple&& other) // - noexcept(detail::all_true({std::is_nothrow_constructible_v...})) // - requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_constructible_v...}) && + constexpr explicit((!std::is_convertible_v || ... || false)) // + Tuple(Tuple&& other) // + noexcept((std::is_nothrow_constructible_v && ... && true)) // + requires(sizeof...(T) == sizeof...(U) && (std::is_constructible_v && ... && true) && detail::is_converting_move_constructor_v) : lambda(other.lambda( [](detail::WrapT&... v_other) @@ -342,9 +327,9 @@ class Tuple // Converting copy-assignment operator. template - constexpr Tuple& operator=(const Tuple& other) // - noexcept(detail::all_true({std::is_nothrow_assignable_v...})) // - requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_assignable_v...})) + constexpr Tuple& operator=(const Tuple& other) // + noexcept((std::is_nothrow_assignable_v && ... && true)) // + requires(sizeof...(T) == sizeof...(U) && (std::is_assignable_v && ... && true)) { lambda( [&other](detail::WrapT&... t) @@ -362,9 +347,9 @@ class Tuple // Converting move-assignment operator. template - constexpr Tuple& operator=(Tuple&& other) // - noexcept(detail::all_true({std::is_nothrow_assignable_v...})) // - requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_assignable_v...})) + constexpr Tuple& operator=(Tuple&& other) // + noexcept((std::is_nothrow_assignable_v && ... && true)) // + requires(sizeof...(T) == sizeof...(U) && (std::is_assignable_v && ... && true)) { lambda( [&other](detail::WrapT&... t) @@ -381,7 +366,7 @@ class Tuple // This comparison operator is SFINAE friendly, which is not required by the C++20 standard. template [[nodiscard]] friend constexpr bool operator==(const Tuple& lhs, const Tuple& rhs) // - requires(sizeof...(T) == sizeof...(U) && (true && ... && detail::WeaklyEqualityComparableWith)) + requires(sizeof...(T) == sizeof...(U) && (detail::WeaklyEqualityComparableWith && ... && true)) { return const_cast(lhs).lambda( [&rhs](const detail::WrapT&... v_lhs) @@ -395,9 +380,9 @@ class Tuple } template - friend constexpr void swap(Tuple& lhs, Tuple& rhs) // - noexcept(detail::all_true({std::is_nothrow_swappable_v...})) // - requires(detail::all_true({std::is_swappable_v...})) + friend constexpr void swap(Tuple& lhs, Tuple& rhs) // + noexcept((std::is_nothrow_swappable_v && ... && true)) // + requires((std::is_swappable_v && ... && true)) { return lhs.lambda( [&rhs](detail::WrapT&... v_lhs) @@ -413,9 +398,9 @@ class Tuple // C++23 overload of swap. template - friend constexpr void swap(const Tuple& lhs, const Tuple& rhs) // - noexcept(detail::all_true({std::is_nothrow_swappable_v...})) // - requires(detail::all_true({std::is_swappable_v...})) + friend constexpr void swap(const Tuple& lhs, const Tuple& rhs) // + noexcept((std::is_nothrow_swappable_v && ... && true)) // + requires((std::is_swappable_v && ... && true)) { return const_cast(lhs).lambda( [&rhs](const detail::WrapT&... v_lhs)