@@ -237,21 +237,6 @@ constexpr decltype(auto) get(ltpl::Tuple<T...>& tuple) noexcept
237
237
}(std::make_index_sequence<I>{});
238
238
}
239
239
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
-
255
240
struct TupleCatIndex
256
241
{
257
242
std::size_t outer;
@@ -276,8 +261,8 @@ class Tuple
276
261
~Tuple () = default ;
277
262
278
263
// 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 )) //
281
266
requires(sizeof ...(T) > 0)
282
267
: lambda(detail::make_lambda<T...>(T()...))
283
268
{
@@ -290,21 +275,21 @@ class Tuple
290
275
// If every element of the Tuple can be implicitly constructed from the arguments then this constructor is also
291
276
// implicit.
292
277
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...>)
298
283
: lambda(detail::make_lambda<T...>(detail::Wrap<T>::wrap(static_cast <U&&>(v))...))
299
284
{
300
285
}
301
286
302
287
// Converting copy constructor
303
288
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 ) &&
308
293
detail::is_converting_copy_constructor_v<Tuple, U...>)
309
294
// We have to const_cast because the lambda's operator() is mutable. But since we cast each element to const& no
310
295
// UB can occur.
@@ -318,10 +303,10 @@ class Tuple
318
303
319
304
// Converting move constructor
320
305
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 ) &&
325
310
detail::is_converting_move_constructor_v<Tuple, U...>)
326
311
: lambda(other.lambda(
327
312
[](detail::WrapT<U>&... v_other)
@@ -342,9 +327,9 @@ class Tuple
342
327
343
328
// Converting copy-assignment operator.
344
329
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 ))
348
333
{
349
334
lambda (
350
335
[&other](detail::WrapT<T>&... t)
@@ -362,9 +347,9 @@ class Tuple
362
347
363
348
// Converting move-assignment operator.
364
349
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 ))
368
353
{
369
354
lambda (
370
355
[&other](detail::WrapT<T>&... t)
@@ -381,7 +366,7 @@ class Tuple
381
366
// This comparison operator is SFINAE friendly, which is not required by the C++20 standard.
382
367
template <class ... U>
383
368
[[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 ))
385
370
{
386
371
return const_cast <Tuple&>(lhs).lambda (
387
372
[&rhs](const detail::WrapT<T>&... v_lhs)
@@ -395,9 +380,9 @@ class Tuple
395
380
}
396
381
397
382
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 ))
401
386
{
402
387
return lhs.lambda (
403
388
[&rhs](detail::WrapT<T>&... v_lhs)
@@ -413,9 +398,9 @@ class Tuple
413
398
414
399
// C++23 overload of swap.
415
400
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 ))
419
404
{
420
405
return const_cast <Tuple&>(lhs).lambda (
421
406
[&rhs](const detail::WrapT<T>&... v_lhs)
0 commit comments