diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index e37c4ac4fddd8c..63adc03fae2980 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -701,6 +701,7 @@ set(files __thread/thread.h __thread/timed_backoff_policy.h __tree + __tuple/find_index.h __tuple/make_tuple_types.h __tuple/pair_like.h __tuple/sfinae_helpers.h diff --git a/libcxx/include/__tuple/find_index.h b/libcxx/include/__tuple/find_index.h new file mode 100644 index 00000000000000..133b00419d0c6c --- /dev/null +++ b/libcxx/include/__tuple/find_index.h @@ -0,0 +1,62 @@ +//===----------------------------------------------------------------------===// +// +// 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___TUPLE_FIND_INDEX_H +#define _LIBCPP___TUPLE_FIND_INDEX_H + +#include <__config> +#include <__type_traits/is_same.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +#if _LIBCPP_STD_VER >= 14 + +_LIBCPP_BEGIN_NAMESPACE_STD + +namespace __find_detail { + +static constexpr size_t __not_found = static_cast(-1); +static constexpr size_t __ambiguous = __not_found - 1; + +inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx_return(size_t __curr_i, size_t __res, bool __matches) { + return !__matches ? __res : (__res == __not_found ? __curr_i : __ambiguous); +} + +template +inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) { + return __i == _Nx + ? __not_found + : __find_detail::__find_idx_return(__i, __find_detail::__find_idx(__i + 1, __matches), __matches[__i]); +} + +template +struct __find_exactly_one_checked { + static constexpr bool __matches[sizeof...(_Args)] = {is_same<_T1, _Args>::value...}; + static constexpr size_t value = __find_detail::__find_idx(0, __matches); + static_assert(value != __not_found, "type not found in type list"); + static_assert(value != __ambiguous, "type occurs more than once in type list"); +}; + +template +struct __find_exactly_one_checked<_T1> { + static_assert(!is_same<_T1, _T1>::value, "type not in empty type list"); +}; + +} // namespace __find_detail + +template +struct __find_exactly_one_t : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_STD_VER >= 14 + +#endif // _LIBCPP___TUPLE_FIND_INDEX_H diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index e02dc8da6ba182..b1e728cde868da 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -697,6 +697,7 @@ { include: [ "<__thread/this_thread.h>", "private", "", "public" ] }, { include: [ "<__thread/thread.h>", "private", "", "public" ] }, { include: [ "<__thread/timed_backoff_policy.h>", "private", "", "public" ] }, + { include: [ "<__tuple/find_index.h>", "private", "", "public" ] }, { include: [ "<__tuple/make_tuple_types.h>", "private", "", "public" ] }, { include: [ "<__tuple/pair_like.h>", "private", "", "public" ] }, { include: [ "<__tuple/sfinae_helpers.h>", "private", "", "public" ] }, diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index 98890e890cdb13..0bd2831b7f159c 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1799,6 +1799,7 @@ module std_private_thread_thread [system] { } module std_private_thread_timed_backoff_policy [system] { header "__thread/timed_backoff_policy.h" } +module std_private_tuple_find_index [system] { header "__tuple/find_index.h" } module std_private_tuple_make_tuple_types [system] { header "__tuple/make_tuple_types.h" } module std_private_tuple_pair_like [system] { header "__tuple/pair_like.h" diff --git a/libcxx/include/tuple b/libcxx/include/tuple index 8808db6739fb9b..e63e4e25a7d2bd 100644 --- a/libcxx/include/tuple +++ b/libcxx/include/tuple @@ -213,6 +213,7 @@ template #include <__fwd/tuple.h> #include <__memory/allocator_arg_t.h> #include <__memory/uses_allocator.h> +#include <__tuple/find_index.h> #include <__tuple/make_tuple_types.h> #include <__tuple/sfinae_helpers.h> #include <__tuple/tuple_element.h> @@ -1087,40 +1088,6 @@ get(const tuple<_Tp...>&& __t) _NOEXCEPT { # if _LIBCPP_STD_VER >= 14 -namespace __find_detail { - -static constexpr size_t __not_found = static_cast(-1); -static constexpr size_t __ambiguous = __not_found - 1; - -inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx_return(size_t __curr_i, size_t __res, bool __matches) { - return !__matches ? __res : (__res == __not_found ? __curr_i : __ambiguous); -} - -template -inline _LIBCPP_HIDE_FROM_ABI constexpr size_t __find_idx(size_t __i, const bool (&__matches)[_Nx]) { - return __i == _Nx - ? __not_found - : __find_detail::__find_idx_return(__i, __find_detail::__find_idx(__i + 1, __matches), __matches[__i]); -} - -template -struct __find_exactly_one_checked { - static constexpr bool __matches[sizeof...(_Args)] = {is_same<_T1, _Args>::value...}; - static constexpr size_t value = __find_detail::__find_idx(0, __matches); - static_assert(value != __not_found, "type not found in type list"); - static_assert(value != __ambiguous, "type occurs more than once in type list"); -}; - -template -struct __find_exactly_one_checked<_T1> { - static_assert(!is_same<_T1, _T1>::value, "type not in empty type list"); -}; - -} // namespace __find_detail - -template -struct __find_exactly_one_t : public __find_detail::__find_exactly_one_checked<_T1, _Args...> {}; - template inline _LIBCPP_HIDE_FROM_ABI constexpr _T1& get(tuple<_Args...>& __tup) noexcept { return std::get<__find_exactly_one_t<_T1, _Args...>::value>(__tup); diff --git a/libcxx/include/variant b/libcxx/include/variant index 5ce99250a8b4f4..d1eea52f0a9301 100644 --- a/libcxx/include/variant +++ b/libcxx/include/variant @@ -221,13 +221,18 @@ namespace std { #include <__functional/operations.h> #include <__functional/unary_function.h> #include <__memory/addressof.h> +#include <__tuple/find_index.h> +#include <__tuple/sfinae_helpers.h> #include <__type_traits/add_const.h> #include <__type_traits/add_cv.h> #include <__type_traits/add_pointer.h> #include <__type_traits/add_volatile.h> +#include <__type_traits/common_type.h> #include <__type_traits/dependent_type.h> #include <__type_traits/is_array.h> +#include <__type_traits/is_default_constructible.h> #include <__type_traits/is_destructible.h> +#include <__type_traits/is_nothrow_assignable.h> #include <__type_traits/is_nothrow_move_constructible.h> #include <__type_traits/is_trivially_copy_assignable.h> #include <__type_traits/is_trivially_copy_constructible.h> @@ -242,6 +247,7 @@ namespace std { #include <__utility/forward.h> #include <__utility/forward_like.h> #include <__utility/in_place.h> +#include <__utility/integer_sequence.h> #include <__utility/move.h> #include <__utility/swap.h> #include <__variant/monostate.h> @@ -249,7 +255,6 @@ namespace std { #include #include #include -#include #include // standard-mandated includes @@ -340,21 +345,20 @@ struct _LIBCPP_TEMPLATE_VIS variant_alternative<_Ip, variant<_Types...>> { inline constexpr size_t variant_npos = static_cast(-1); -_LIBCPP_HIDE_FROM_ABI constexpr int __choose_index_type(unsigned int __num_elem) { - if (__num_elem < numeric_limits::max()) - return 0; - if (__num_elem < numeric_limits::max()) - return 1; - return 2; +template +_LIBCPP_HIDE_FROM_ABI constexpr auto __choose_index_type() { +#ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + if constexpr (_NumAlternatives < numeric_limits::max()) + return static_cast(0); + else if constexpr (_NumAlternatives < numeric_limits::max()) + return static_cast(0); + else +#endif // _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + return static_cast(0); } template -using __variant_index_t = -# ifndef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION - unsigned int; -# else - std::tuple_element_t< __choose_index_type(_NumAlts), std::tuple >; -# endif +using __variant_index_t = decltype(std::__choose_index_type<_NumAlts>()); template constexpr _IndexType __variant_npos = static_cast<_IndexType>(-1); @@ -1625,6 +1629,7 @@ _LIBCPP_POP_MACROS #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include +# include # include # include # include diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index 64ff9261820a96..436aa52b6de875 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -662,7 +662,6 @@ variant cstring variant initializer_list variant limits variant new -variant tuple variant version vector array vector cctype diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index 64ff9261820a96..436aa52b6de875 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -662,7 +662,6 @@ variant cstring variant initializer_list variant limits variant new -variant tuple variant version vector array vector cctype diff --git a/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp b/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp index 9011e61e78808a..2f1ea8bffb479b 100644 --- a/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp +++ b/libcxx/test/libcxx/utilities/variant/variant.variant/variant_size.pass.cpp @@ -49,13 +49,13 @@ void test_index_type() { template void test_index_internals() { using Lim = std::numeric_limits; - static_assert(std::__choose_index_type(Lim::max() -1) != - std::__choose_index_type(Lim::max()), ""); - static_assert(std::is_same_v< - std::__variant_index_t, - std::__variant_index_t - > == ExpectEqual, ""); - using IndexT = std::__variant_index_t; +#ifdef _LIBCPP_ABI_VARIANT_INDEX_TYPE_OPTIMIZATION + static_assert(!std::is_same_v()), + decltype(std::__choose_index_type())>); +#endif + static_assert( + std::is_same_v, std::__variant_index_t > == ExpectEqual, ""); + using IndexT = std::__variant_index_t; using IndexLim = std::numeric_limits; static_assert(std::__variant_npos == IndexLim::max(), ""); } diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp index 1d05eb5fe76e97..00f27c3220d2ed 100644 --- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp +++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.elem/tuple.by.type.verify.cpp @@ -18,13 +18,13 @@ struct UserType {}; void test_bad_index() { std::tuple t1; - TEST_IGNORE_NODISCARD std::get(t1); // expected-error@tuple:* {{type not found}} + TEST_IGNORE_NODISCARD std::get(t1); // expected-error@*:* {{type not found}} TEST_IGNORE_NODISCARD std::get(t1); // expected-note {{requested here}} TEST_IGNORE_NODISCARD std::get(t1); // expected-note {{requested here}} - // expected-error@tuple:* 2 {{type occurs more than once}} + // expected-error@*:* 2 {{type occurs more than once}} std::tuple<> t0; TEST_IGNORE_NODISCARD std::get(t0); // expected-node {{requested here}} - // expected-error@tuple:* 1 {{type not in empty type list}} + // expected-error@*:* {{type not in empty type list}} } void test_bad_return_type() { diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp index 68706d6c32af4f..50e7fc81387abc 100644 --- a/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit.pass.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include diff --git a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp index 20472c62fc5f98..b005f303bc4b6c 100644 --- a/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit.member/visit_return_type.pass.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp index 097b784f2bf2ce..798ce7ded72a60 100644 --- a/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit.pass.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include diff --git a/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp b/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp index eb425c07f93222..b1189dff656db4 100644 --- a/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp +++ b/libcxx/test/std/utilities/variant/variant.visit/visit_return_type.pass.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include