diff --git a/libcxx/docs/Status/RangesPaper.csv b/libcxx/docs/Status/RangesPaper.csv --- a/libcxx/docs/Status/RangesPaper.csv +++ b/libcxx/docs/Status/RangesPaper.csv @@ -1,5 +1,5 @@ Section,Description,Dependencies,Assignee,Complete -`[tuple.helper] `_,Update includes.,None,Konstantin Varlamov,Not started +`[tuple.helper] `_,`Update includes. `_,None,Konstantin Varlamov,✅ `[range.cmp] `_,"| `ranges::equal_to `_ | `ranges::not_equal_to `_ | `ranges::less `_ diff --git a/libcxx/include/ranges b/libcxx/include/ranges --- a/libcxx/include/ranges +++ b/libcxx/include/ranges @@ -198,6 +198,36 @@ class join_view; } +namespace std { + namespace views = ranges::views; + + template struct tuple_size; + template struct tuple_element; + + template + struct tuple_size> + : integral_constant {}; + + template + struct tuple_element<0, ranges::subrange> { + using type = I; + }; + + template + struct tuple_element<1, ranges::subrange> { + using type = S; + }; + + template + struct tuple_element<0, const ranges::subrange> { + using type = I; + }; + + template + struct tuple_element<1, const ranges::subrange> { + using type = S; + }; +} */ // Make sure all feature-test macros are available. diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.ranges.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.ranges.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.ranges.pass.cpp @@ -0,0 +1,64 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17 +// UNSUPPORTED: libcpp-no-concepts +// UNSUPPORTED: libcpp-has-no-incomplete-ranges + +// + +// template struct tuple_size; +// template struct tuple_element; + +#include +// Note: make sure to not include `` (or any other header including ``) because it also makes some +// tuple specializations available, thus obscuring whether the `` includes work correctly. + +using Iterator = int*; + +class SizedSentinel { +public: + constexpr bool operator==(int*) const; + friend constexpr ptrdiff_t operator-(const SizedSentinel&, int*); + friend constexpr ptrdiff_t operator-(int*, const SizedSentinel&); +}; + +static_assert(std::sized_sentinel_for); +using SizedRange = std::ranges::subrange; + +using UnsizedSentinel = std::unreachable_sentinel_t; +static_assert(!std::sized_sentinel_for); +using UnsizedRange = std::ranges::subrange; + +// Because the sentinel is unsized while the subrange is sized, an additional integer member will be used to store the +// size -- make sure it doesn't affect the value of `tuple_size`. +using ThreeElementRange = std::ranges::subrange; +static_assert(std::ranges::sized_range); + +static_assert(std::tuple_size::value == 2); +static_assert(std::tuple_size::value == 2); +static_assert(std::tuple_size::value == 2); + +template +constexpr bool test_tuple_element() { + static_assert(std::same_as::type, Expected>); + static_assert(std::same_as::type, Expected>); + // Note: the Standard does not mandate a specialization of `tuple_element` for volatile, so trying a `volatile Range` + // would fail to compile. + + return true; +} + +int main(int, char**) { + static_assert(test_tuple_element<0, SizedRange, Iterator>()); + static_assert(test_tuple_element<1, SizedRange, SizedSentinel>()); + static_assert(test_tuple_element<0, UnsizedRange, Iterator>()); + static_assert(test_tuple_element<1, UnsizedRange, UnsizedSentinel>()); + + return 0; +}