|
1 | 1 | #pragma once |
2 | 2 |
|
| 3 | +#include <stdx/type_traits.hpp> |
3 | 4 | #include <stdx/udls.hpp> |
4 | 5 | #include <stdx/utility.hpp> |
5 | 6 |
|
@@ -335,18 +336,6 @@ struct tuple_impl<std::index_sequence<Is...>, index_function_list<Fs...>, Ts...> |
335 | 336 | constexpr static auto size = |
336 | 337 | std::integral_constant<std::size_t, sizeof...(Ts)>{}; |
337 | 338 |
|
338 | | - [[nodiscard]] constexpr static auto fill_inner_indices(index_pair *p) |
339 | | - -> index_pair * { |
340 | | - ((p++->inner = Is), ...); |
341 | | - return p; |
342 | | - } |
343 | | - [[nodiscard]] constexpr static auto |
344 | | - fill_outer_indices(index_pair *p, [[maybe_unused]] std::size_t n) |
345 | | - -> index_pair * { |
346 | | - ((p++->outer = (static_cast<void>(Is), n)), ...); |
347 | | - return p; |
348 | | - } |
349 | | - |
350 | 339 | private: |
351 | 340 | template <typename Funcs, typename... Us> |
352 | 341 | requires(... and std::equality_comparable_with<Ts, Us>) |
@@ -407,18 +396,56 @@ tuple_impl(Ts...) |
407 | 396 | template <typename T> constexpr auto tuple_size_v = T::size(); |
408 | 397 | template <typename T, std::size_t N> |
409 | 398 | constexpr auto tuple_size_v<std::array<T, N>> = N; |
| 399 | +template <typename T, typename U> |
| 400 | +constexpr auto tuple_size_v<std::pair<T, U>> = std::size_t{2}; |
410 | 401 | template <typename T, T N> |
411 | 402 | constexpr auto tuple_size_v<make_integer_sequence<T, N>> = std::size_t{N}; |
412 | 403 |
|
413 | | -template <std::size_t I, typename T> |
414 | | -using tuple_element_t = typename T::template element_t<I>; |
415 | | - |
416 | 404 | template <typename T> |
417 | 405 | concept tuple_comparable = requires { typename T::common_tuple_comparable; }; |
418 | 406 |
|
419 | 407 | template <typename T> |
420 | 408 | concept tuplelike = requires { typename remove_cvref_t<T>::is_tuple; }; |
421 | 409 |
|
| 410 | +template <std::size_t I, typename T> struct tuple_element; |
| 411 | + |
| 412 | +template <std::size_t I, tuplelike T> struct tuple_element<I, T> { |
| 413 | + using type = typename T::template element_t<I>; |
| 414 | +}; |
| 415 | + |
| 416 | +template <std::size_t I, typename T, std::size_t N> |
| 417 | +struct tuple_element<I, std::array<T, N>> { |
| 418 | + using type = T; |
| 419 | +}; |
| 420 | + |
| 421 | +template <std::size_t I, typename T, typename U> |
| 422 | +struct tuple_element<I, std::pair<T, U>> { |
| 423 | + using type = nth_t<I, T, U>; |
| 424 | +}; |
| 425 | + |
| 426 | +template <std::size_t I, typename T> |
| 427 | +using tuple_element_t = typename tuple_element<I, T>::type; |
| 428 | + |
| 429 | +namespace detail { |
| 430 | +template <typename T> |
| 431 | +concept has_vacuous_tuple_protocol = requires { |
| 432 | + { |
| 433 | + tuple_size_v<std::remove_cvref_t<T>> |
| 434 | + } -> std::same_as<std::size_t const &>; |
| 435 | +}; |
| 436 | +template <typename T> |
| 437 | +concept is_vacuous_tuple = tuple_size_v<std::remove_cvref_t<T>> == 0; |
| 438 | +} // namespace detail |
| 439 | + |
| 440 | +template <typename T> |
| 441 | +concept has_tuple_protocol = |
| 442 | + detail::has_vacuous_tuple_protocol<T> and |
| 443 | + (detail::is_vacuous_tuple<T> or requires(T &t) { |
| 444 | + { |
| 445 | + get<0>(t) |
| 446 | + } -> std::same_as<tuple_element_t<0, std::remove_cvref_t<T>> &>; |
| 447 | + }); |
| 448 | + |
422 | 449 | template <typename... Ts> |
423 | 450 | class tuple : public detail::tuple_impl<std::index_sequence_for<Ts...>, |
424 | 451 | detail::index_function_list<>, Ts...> { |
@@ -524,6 +551,5 @@ class one_of : public detail::tuple_impl<std::index_sequence_for<Ts...>, |
524 | 551 | } |
525 | 552 | }; |
526 | 553 | template <typename... Ts> one_of(Ts...) -> one_of<Ts...>; |
527 | | - |
528 | 554 | } // namespace v1 |
529 | 555 | } // namespace stdx |
0 commit comments