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/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -349,6 +349,7 @@ __ranges/subrange.h __ranges/take_view.h __ranges/transform_view.h + __ranges/tuple_specializations.h __ranges/view_interface.h __split_buffer __std_stream diff --git a/libcxx/include/__ranges/tuple_specializations.h b/libcxx/include/__ranges/tuple_specializations.h new file mode 100644 --- /dev/null +++ b/libcxx/include/__ranges/tuple_specializations.h @@ -0,0 +1,58 @@ +// -*- C++ -*- +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___RANGES_TUPLE_SPECIALIZATIONS_ +#define _LIBCPP___RANGES_TUPLE_SPECIALIZATIONS_ + +#include <__config> +#include <__tuple> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +#pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if !defined(_LIBCPP_HAS_NO_CONCEPTS) + +namespace std { + template struct tuple_size; + template struct tuple_element; + + template + struct tuple_size> + : integral_constant { + }; + + template + struct tuple_element<0, ranges::subrange<_Iterator, _Sentinel, _Kind>> { + using type = _Iterator; + }; + + template + struct tuple_element<1, ranges::subrange<_Iterator, _Sentinel, _Kind>> { + using type = _Sentinel; + }; + + template + struct tuple_element<0, const ranges::subrange<_Iterator, _Sentinel, _Kind>> { + using type = _Iterator; + }; + + template + struct tuple_element<1, const ranges::subrange<_Iterator, _Sentinel, _Kind>> { + using type = _Sentinel; + }; +} + +#endif // !defined(_LIBCPP_HAS_NO_CONCEPTS) + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___RANGES_TUPLE_SPECIALIZATIONS_ diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -815,6 +815,7 @@ export functional.__functional.bind_back export functional.__functional.perfect_forward } + module tuple_specializations { private header "__ranges/tuple_specializations.h" } module view_interface { private header "__ranges/view_interface.h" } } } 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. @@ -227,6 +257,7 @@ #include <__ranges/subrange.h> #include <__ranges/take_view.h> #include <__ranges/transform_view.h> +#include <__ranges/tuple_specializations.h> #include <__ranges/view_interface.h> #include // Required by the standard. #include // Required by the standard. diff --git a/libcxx/test/std/ranges/tuple_specializations.compile.pass.cpp b/libcxx/test/std/ranges/tuple_specializations.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/ranges/tuple_specializations.compile.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// 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 +#include +#include + +#include "test_iterators.h" +#include "test_macros.h" + +using Iterator = int*; + +using SizedSentinel = sized_sentinel; +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; + +static_assert(std::tuple_size::value == 2); +static_assert(std::tuple_size::value == 2); + +template +constexpr bool test_tuple_element() { + static_assert(std::is_same_v::type, Expected>); + static_assert(std::is_same_v::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; +} diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.array.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.array.pass.cpp --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.array.pass.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.array.pass.cpp @@ -16,8 +16,7 @@ // typedef Ti type; // }; // -// LWG #2212 says that tuple_size and tuple_element must be -// available after including +// LWG #2212 says that tuple_size and tuple_element must be available after including . #include #include diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.ranges.compile.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.ranges.compile.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.helper/tuple.include.ranges.compile.pass.cpp @@ -0,0 +1,11 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// + +// Tested in ranges/tuple_specializations.compile.pass.cpp