Skip to content

Commit 43a797b

Browse files
committed
perf: Replace all_true with fold expression, not supporting tuples with more than 256 elements and default compile flags for now
1 parent 0e38981 commit 43a797b

File tree

1 file changed

+28
-43
lines changed

1 file changed

+28
-43
lines changed

src/ltpl/tuple.hpp

+28-43
Original file line numberDiff line numberDiff line change
@@ -237,21 +237,6 @@ constexpr decltype(auto) get(ltpl::Tuple<T...>& tuple) noexcept
237237
}(std::make_index_sequence<I>{});
238238
}
239239

240-
constexpr bool all_true(Access) noexcept { return true; }
241-
242-
template <std::size_t N>
243-
constexpr bool all_true(bool const (&array)[N]) noexcept
244-
{
245-
for (bool ok : array)
246-
{
247-
if (!ok)
248-
{
249-
return false;
250-
}
251-
}
252-
return true;
253-
}
254-
255240
struct TupleCatIndex
256241
{
257242
std::size_t outer;
@@ -276,8 +261,8 @@ class Tuple
276261
~Tuple() = default;
277262

278263
// Non-empty Tuple, default construct all elements.
279-
constexpr Tuple() //
280-
noexcept(detail::all_true({detail::NothrowDefaultAndMoveConstructible<T>...})) //
264+
constexpr Tuple() //
265+
noexcept((detail::NothrowDefaultAndMoveConstructible<T> && ... && true)) //
281266
requires(sizeof...(T) > 0)
282267
: lambda(detail::make_lambda<T...>(T()...))
283268
{
@@ -290,21 +275,21 @@ class Tuple
290275
// If every element of the Tuple can be implicitly constructed from the arguments then this constructor is also
291276
// implicit.
292277
template <class... U>
293-
constexpr explicit(!detail::all_true({std::is_convertible_v<U, T>...})) //
294-
Tuple(U&&... v) //
295-
noexcept(detail::all_true({std::is_nothrow_constructible_v<T, U>...})) //
296-
requires(sizeof...(T) == sizeof...(U) && sizeof...(T) >= 1 &&
297-
detail::all_true({std::is_constructible_v<T, U>...}) && detail::is_not_exactly_v<Tuple, U...>)
278+
constexpr explicit((!std::is_convertible_v<U, T> || ... || false)) //
279+
Tuple(U&&... v) //
280+
noexcept((std::is_nothrow_constructible_v<T, U> && ... && true)) //
281+
requires(sizeof...(T) == sizeof...(U) && sizeof...(T) >= 1 && (std::is_constructible_v<T, U> && ... && true) &&
282+
detail::is_not_exactly_v<Tuple, U...>)
298283
: lambda(detail::make_lambda<T...>(detail::Wrap<T>::wrap(static_cast<U&&>(v))...))
299284
{
300285
}
301286

302287
// Converting copy constructor
303288
template <class... U>
304-
constexpr explicit(!detail::all_true({std::is_convertible_v<const U&, T>...})) //
305-
Tuple(const Tuple<U...>& other) //
306-
noexcept(detail::all_true({std::is_nothrow_constructible_v<T, const U&>...})) //
307-
requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_constructible_v<T, const U&>...}) &&
289+
constexpr explicit((!std::is_convertible_v<const U&, T> || ... || false)) //
290+
Tuple(const Tuple<U...>& other) //
291+
noexcept((std::is_nothrow_constructible_v<T, const U&> && ... && true)) //
292+
requires(sizeof...(T) == sizeof...(U) && (std::is_constructible_v<T, const U&> && ... && true) &&
308293
detail::is_converting_copy_constructor_v<Tuple, U...>)
309294
// We have to const_cast because the lambda's operator() is mutable. But since we cast each element to const& no
310295
// UB can occur.
@@ -318,10 +303,10 @@ class Tuple
318303

319304
// Converting move constructor
320305
template <class... U>
321-
constexpr explicit(!detail::all_true({std::is_convertible_v<U, T>...})) //
322-
Tuple(Tuple<U...>&& other) //
323-
noexcept(detail::all_true({std::is_nothrow_constructible_v<T, const U&>...})) //
324-
requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_constructible_v<T, U>...}) &&
306+
constexpr explicit((!std::is_convertible_v<U, T> || ... || false)) //
307+
Tuple(Tuple<U...>&& other) //
308+
noexcept((std::is_nothrow_constructible_v<T, const U&> && ... && true)) //
309+
requires(sizeof...(T) == sizeof...(U) && (std::is_constructible_v<T, U> && ... && true) &&
325310
detail::is_converting_move_constructor_v<Tuple, U...>)
326311
: lambda(other.lambda(
327312
[](detail::WrapT<U>&... v_other)
@@ -342,9 +327,9 @@ class Tuple
342327

343328
// Converting copy-assignment operator.
344329
template <class... U>
345-
constexpr Tuple& operator=(const Tuple<U...>& other) //
346-
noexcept(detail::all_true({std::is_nothrow_assignable_v<T&, const U&>...})) //
347-
requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_assignable_v<T&, const U&>...}))
330+
constexpr Tuple& operator=(const Tuple<U...>& other) //
331+
noexcept((std::is_nothrow_assignable_v<T&, const U&> && ... && true)) //
332+
requires(sizeof...(T) == sizeof...(U) && (std::is_assignable_v<T&, const U&> && ... && true))
348333
{
349334
lambda(
350335
[&other](detail::WrapT<T>&... t)
@@ -362,9 +347,9 @@ class Tuple
362347

363348
// Converting move-assignment operator.
364349
template <class... U>
365-
constexpr Tuple& operator=(Tuple<U...>&& other) //
366-
noexcept(detail::all_true({std::is_nothrow_assignable_v<T&, U>...})) //
367-
requires(sizeof...(T) == sizeof...(U) && detail::all_true({std::is_assignable_v<T&, U>...}))
350+
constexpr Tuple& operator=(Tuple<U...>&& other) //
351+
noexcept((std::is_nothrow_assignable_v<T&, U> && ... && true)) //
352+
requires(sizeof...(T) == sizeof...(U) && (std::is_assignable_v<T&, U> && ... && true))
368353
{
369354
lambda(
370355
[&other](detail::WrapT<T>&... t)
@@ -381,7 +366,7 @@ class Tuple
381366
// This comparison operator is SFINAE friendly, which is not required by the C++20 standard.
382367
template <class... U>
383368
[[nodiscard]] friend constexpr bool operator==(const Tuple& lhs, const Tuple<U...>& rhs) //
384-
requires(sizeof...(T) == sizeof...(U) && (true && ... && detail::WeaklyEqualityComparableWith<T, U>))
369+
requires(sizeof...(T) == sizeof...(U) && (detail::WeaklyEqualityComparableWith<T, U> && ... && true))
385370
{
386371
return const_cast<Tuple&>(lhs).lambda(
387372
[&rhs](const detail::WrapT<T>&... v_lhs)
@@ -395,9 +380,9 @@ class Tuple
395380
}
396381

397382
template <class... U>
398-
friend constexpr void swap(Tuple& lhs, Tuple& rhs) //
399-
noexcept(detail::all_true({std::is_nothrow_swappable_v<T>...})) //
400-
requires(detail::all_true({std::is_swappable_v<T>...}))
383+
friend constexpr void swap(Tuple& lhs, Tuple& rhs) //
384+
noexcept((std::is_nothrow_swappable_v<T> && ... && true)) //
385+
requires((std::is_swappable_v<T> && ... && true))
401386
{
402387
return lhs.lambda(
403388
[&rhs](detail::WrapT<T>&... v_lhs)
@@ -413,9 +398,9 @@ class Tuple
413398

414399
// C++23 overload of swap.
415400
template <class... U>
416-
friend constexpr void swap(const Tuple& lhs, const Tuple& rhs) //
417-
noexcept(detail::all_true({std::is_nothrow_swappable_v<const T>...})) //
418-
requires(detail::all_true({std::is_swappable_v<const T>...}))
401+
friend constexpr void swap(const Tuple& lhs, const Tuple& rhs) //
402+
noexcept((std::is_nothrow_swappable_v<const T> && ... && true)) //
403+
requires((std::is_swappable_v<const T> && ... && true))
419404
{
420405
return const_cast<Tuple&>(lhs).lambda(
421406
[&rhs](const detail::WrapT<T>&... v_lhs)

0 commit comments

Comments
 (0)