diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 908d46b711a5..a7f108c44e71 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -40,6 +40,7 @@ Implemented Papers - P2637R3 - Member ``visit`` - P2652R2 - Disallow User Specialization of ``allocator_traits`` +- P2819R2 - Add ``tuple`` protocol to ``complex`` Improvements and New Features diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index a62faee4f44e..1c895f79a4c0 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -39,7 +39,7 @@ "`P2868R3 `__","LWG","Remove Deprecated ``std::allocator`` Typedef From C++26","Kona November 2023","|Complete|","18.0","" "`P2870R3 `__","LWG","Remove ``basic_string::reserve()`` From C++26","Kona November 2023","|Complete|","18.0","" "`P2871R3 `__","LWG","Remove Deprecated Unicode Conversion Facets from C++26","Kona November 2023","|Complete|","18.0","" -"`P2819R2 `__","LWG","Add tuple protocol to complex","Kona November 2023","","","" +"`P2819R2 `__","LWG","Add tuple protocol to complex","Kona November 2023","|Complete|","19.0","" "`P2937R0 `__","LWG","Freestanding: Remove ``strtok``","Kona November 2023","","","" "`P2833R2 `__","LWG","Freestanding Library: inout expected span","Kona November 2023","","","" "`P2836R1 `__","LWG","``std::basic_const_iterator`` should follow its underlying type's convertibility","Kona November 2023","","","|DR|" diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index fa3b464e56c4..cafd8c6e00d9 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -429,6 +429,7 @@ set(files __functional/weak_result_type.h __fwd/array.h __fwd/bit_reference.h + __fwd/complex.h __fwd/fstream.h __fwd/hash.h __fwd/ios.h diff --git a/libcxx/include/__fwd/complex.h b/libcxx/include/__fwd/complex.h new file mode 100644 index 000000000000..22c78c5cc3c7 --- /dev/null +++ b/libcxx/include/__fwd/complex.h @@ -0,0 +1,42 @@ +//===---------------------------------------------------------------------===// +// +// 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___FWD_COMPLEX_H +#define _LIBCPP___FWD_COMPLEX_H + +#include <__config> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +class _LIBCPP_TEMPLATE_VIS complex; + +#if _LIBCPP_STD_VER >= 26 + +template +_LIBCPP_HIDE_FROM_ABI constexpr _Tp& get(complex<_Tp>&) noexcept; + +template +_LIBCPP_HIDE_FROM_ABI constexpr _Tp&& get(complex<_Tp>&&) noexcept; + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& get(const complex<_Tp>&) noexcept; + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& get(const complex<_Tp>&&) noexcept; + +#endif // _LIBCPP_STD_VER >= 26 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_COMPLEX_H diff --git a/libcxx/include/__ranges/elements_view.h b/libcxx/include/__ranges/elements_view.h index 3f35e93b3071..f159f53dc0a8 100644 --- a/libcxx/include/__ranges/elements_view.h +++ b/libcxx/include/__ranges/elements_view.h @@ -16,6 +16,7 @@ #include <__concepts/derived_from.h> #include <__concepts/equality_comparable.h> #include <__config> +#include <__fwd/complex.h> #include <__iterator/concepts.h> #include <__iterator/iterator_traits.h> #include <__ranges/access.h> diff --git a/libcxx/include/__tuple/tuple_like.h b/libcxx/include/__tuple/tuple_like.h index 3548af971ce2..967e4a543c03 100644 --- a/libcxx/include/__tuple/tuple_like.h +++ b/libcxx/include/__tuple/tuple_like.h @@ -11,6 +11,7 @@ #include <__config> #include <__fwd/array.h> +#include <__fwd/complex.h> #include <__fwd/pair.h> #include <__fwd/subrange.h> #include <__fwd/tuple.h> @@ -40,6 +41,13 @@ struct __tuple_like_impl > : true_type {}; template struct __tuple_like_impl > : true_type {}; +# if _LIBCPP_STD_VER >= 26 + +template +struct __tuple_like_impl> : true_type {}; + +# endif + template concept __tuple_like = __tuple_like_impl>::value; diff --git a/libcxx/include/complex b/libcxx/include/complex index 02b9db8c516d..0aba60e514ba 100644 --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -227,12 +227,41 @@ template complex sqrt (const complex&); template complex tan (const complex&); template complex tanh (const complex&); + // [complex.tuple], tuple interface + template struct tuple_size; // Since C++26 + template struct tuple_element; // Since C++26 + template struct tuple_size>; // Since C++26 + template struct tuple_element>; // Since C++26 + template + constexpr T& get(complex&) noexcept; // Since C++26 + template + constexpr T&& get(complex&&) noexcept; // Since C++26 + template + constexpr const T& get(const complex&) noexcept; // Since C++26 + template + constexpr const T&& get(const complex&&) noexcept; // Since C++26 + + // [complex.literals], complex literals + inline namespace literals { + inline namespace complex_literals { + constexpr complex operator""il(long double); // Since C++14 + constexpr complex operator""il(unsigned long long); // Since C++14 + constexpr complex operator""i(long double); // Since C++14 + constexpr complex operator""i(unsigned long long); // Since C++14 + constexpr complex operator""if(long double); // Since C++14 + constexpr complex operator""if(unsigned long long); // Since C++14 + } + } } // std */ #include <__assert> // all public C++ headers provide the assertion handler #include <__config> +#include <__fwd/complex.h> +#include <__tuple/tuple_element.h> +#include <__tuple/tuple_size.h> +#include <__utility/move.h> #include #include @@ -244,6 +273,9 @@ template complex tanh (const complex&); # pragma GCC system_header #endif +_LIBCPP_PUSH_MACROS +#include <__undef_macros> + _LIBCPP_BEGIN_NAMESPACE_STD template @@ -331,6 +363,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; template <> @@ -408,6 +454,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; template <> @@ -480,6 +540,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; template <> @@ -553,6 +627,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; inline _LIBCPP_CONSTEXPR complex::complex(const complex& __c) : __re_(__c.real()), __im_(__c.imag()) {} @@ -1352,6 +1440,67 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) { } #endif // !_LIBCPP_HAS_NO_LOCALIZATION +#if _LIBCPP_STD_VER >= 26 + +// [complex.tuple], tuple interface + +template +struct tuple_size; + +template +struct tuple_size> : integral_constant {}; + +template +struct tuple_element; + +template +struct tuple_element<_Ip, complex<_Tp>> { + static_assert(_Ip < 2, "Index value is out of range."); + using type = _Tp; +}; + +template +_LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>& __z) noexcept { + static_assert(_Ip < 2, "Index value is out of range."); + if constexpr (_Ip == 0) { + return __z.__re_; + } else { + return __z.__im_; + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&& __z) noexcept { + static_assert(_Ip < 2, "Index value is out of range."); + if constexpr (_Ip == 0) { + return std::move(__z.__re_); + } else { + return std::move(__z.__im_); + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>& __z) noexcept { + static_assert(_Ip < 2, "Index value is out of range."); + if constexpr (_Ip == 0) { + return __z.__re_; + } else { + return __z.__im_; + } +} + +template +_LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&& __z) noexcept { + static_assert(_Ip < 2, "Index value is out of range."); + if constexpr (_Ip == 0) { + return std::move(__z.__re_); + } else { + return std::move(__z.__im_); + } +} + +#endif // _LIBCPP_STD_VER >= 26 + #if _LIBCPP_STD_VER >= 14 // Literal suffix for complex number literals [complex.literals] inline namespace literals { @@ -1383,6 +1532,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr complex operator""if(unsigned long _LIBCPP_END_NAMESPACE_STD +_LIBCPP_POP_MACROS + #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20 # include # include diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index fbe09fa5e54a..22fbea99b848 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -424,6 +424,7 @@ { include: [ "<__fwd/array.h>", "private", "", "public" ] }, { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, { include: [ "<__fwd/bit_reference.h>", "private", "", "public" ] }, + { include: [ "<__fwd/complex.h>", "private", "", "public" ] }, { include: [ "<__fwd/fstream.h>", "private", "", "public" ] }, { include: [ "<__fwd/hash.h>", "private", "", "public" ] }, { include: [ "<__fwd/ios.h>", "private", "", "public" ] }, diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index e72136a58c0b..219906aa9a56 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1195,6 +1195,8 @@ module std_private_compare_synth_three_way [system] { header "__c module std_private_compare_three_way_comparable [system] { header "__compare/three_way_comparable.h" } module std_private_compare_weak_order [system] { header "__compare/weak_order.h" } +module std_private_complex_complex_fwd [system] { header "__fwd/complex.h" } + module std_private_concepts_arithmetic [system] { header "__concepts/arithmetic.h" } module std_private_concepts_assignable [system] { header "__concepts/assignable.h" } module std_private_concepts_boolean_testable [system] { header "__concepts/boolean_testable.h" } diff --git a/libcxx/modules/std/complex.inc b/libcxx/modules/std/complex.inc index 3ccf44fa0224..47a44420b127 100644 --- a/libcxx/modules/std/complex.inc +++ b/libcxx/modules/std/complex.inc @@ -59,6 +59,13 @@ export namespace std { using std::tan; using std::tanh; +#if _LIBCPP_STD_VER >= 26 + // [complex.tuple], tuple interface + using std::get; + using std::tuple_element; + using std::tuple_size; +#endif + // [complex.literals], complex literals inline namespace literals { inline namespace complex_literals { diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv index caeb0f65c145..0acc48c80eb7 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx03.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv @@ -159,6 +159,7 @@ compare limits compare type_traits compare version complex cmath +complex cstddef complex iosfwd complex sstream complex stdexcept diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv index fe0d95b6bf7e..d2acb1356d13 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx11.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx11.csv @@ -160,6 +160,7 @@ compare limits compare type_traits compare version complex cmath +complex cstddef complex iosfwd complex sstream complex stdexcept diff --git a/libcxx/test/libcxx/transitive_includes/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv index 1ad62ef78350..ccba63f44cb2 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx14.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx14.csv @@ -160,6 +160,7 @@ compare limits compare type_traits compare version complex cmath +complex cstddef complex iosfwd complex sstream complex stdexcept diff --git a/libcxx/test/libcxx/transitive_includes/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv index 1ad62ef78350..ccba63f44cb2 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx17.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx17.csv @@ -160,6 +160,7 @@ compare limits compare type_traits compare version complex cmath +complex cstddef complex iosfwd complex sstream complex stdexcept diff --git a/libcxx/test/libcxx/transitive_includes/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv index e5bfe1320dec..aa9239bda21f 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx20.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv @@ -166,6 +166,7 @@ compare limits compare type_traits compare version complex cmath +complex cstddef complex iosfwd complex sstream complex stdexcept diff --git a/libcxx/test/libcxx/transitive_includes/cxx23.csv b/libcxx/test/libcxx/transitive_includes/cxx23.csv index c398cea7e47c..44b5f78beea4 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx23.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv @@ -111,6 +111,7 @@ compare cstdint compare limits compare version complex cmath +complex cstddef complex sstream complex version concepts cstddef diff --git a/libcxx/test/libcxx/transitive_includes/cxx26.csv b/libcxx/test/libcxx/transitive_includes/cxx26.csv index c398cea7e47c..44b5f78beea4 100644 --- a/libcxx/test/libcxx/transitive_includes/cxx26.csv +++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv @@ -111,6 +111,7 @@ compare cstdint compare limits compare version complex cmath +complex cstddef complex sstream complex version concepts cstddef diff --git a/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp new file mode 100644 index 000000000000..b1d199865dec --- /dev/null +++ b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// + +// 22.4.3 Concept `tuple-like` [tuple.like] +// +// template +// concept tuple-like; // exposition only + +#include +#include +#include +#include + +#include "test_iterators.h" + +// Non-tuple-like type + +static_assert(!std::__tuple_like); + +// Tuple-like: array + +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); + +// Tuple-like: complex + +#if _LIBCPP_STD_VER >= 26 +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); +#endif + +// Tuple-like: pair + +static_assert(std::__tuple_like>); + +// Tuple-like: tuple + +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); + +// Support for + +using FI = forward_iterator; +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); +static_assert(std::__tuple_like>); + +template +void test_subrange_sized() { + static_assert(std::__tuple_like>); +} + +template +void test_subrange_unsized() { + static_assert(std::__tuple_like>); +} + +void test() { + test_subrange_sized>(); + test_subrange_sized>(); + test_subrange_sized>(); + test_subrange_sized>(); + test_subrange_sized(); + + test_subrange_sized>(); + test_subrange_sized>(); + test_subrange_sized>(); + test_subrange_sized>(); + test_subrange_sized(); + + test_subrange_unsized>(); + test_subrange_unsized>(); + static_assert(std::__tuple_like>); + + test_subrange_unsized>(); + test_subrange_unsized>(); + static_assert( + std::__tuple_like>); +} diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp new file mode 100644 index 000000000000..bd514a672cdc --- /dev/null +++ b/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp @@ -0,0 +1,133 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20, c++23 + +// + +// template +// constexpr T& get(complex&) noexcept; +// template +// constexpr T&& get(complex&&) noexcept; +// template +// constexpr const T& get(const complex&) noexcept; +// template +// constexpr const T&& get(const complex&&) noexcept; + +#include +#include +#include +#include +#include +#include + +template +constexpr void test() { + // & + { + std::complex c{T{27}, T{28}}; + + std::same_as decltype(auto) r = get<0>(c); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + std::same_as decltype(auto) i = get<1>(c); + static_assert(noexcept(get<1>(c))); + assert(i == T{28}); + } + // && + { + std::complex c{T{27}, T{28}}; + + std::same_as decltype(auto) r = get<0>(std::move(c)); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + } + { + std::complex c{T{27}, T{28}}; + + std::same_as decltype(auto) i = get<1>(std::move(c)); + static_assert(noexcept(get<1>(c))); + assert(i == T{28}); + } + // const & + { + const std::complex c{T{27}, T{28}}; + + std::same_as decltype(auto) r = get<0>(c); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + std::same_as decltype(auto) i = get<1>(c); + static_assert(noexcept(get<1>(c))); + assert(i == T{28}); + } + // const && + { + const std::complex c{T{27}, T{28}}; + + std::same_as decltype(auto) r = get<0>(std::move(c)); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + } + { + const std::complex c{T{27}, T{28}}; + + std::same_as decltype(auto) i = get<1>(std::move(c)); + static_assert(noexcept(get<1>(c))); + assert(i == T{28}); + } + // `get()` allows using `complex` with structured bindings + { + std::complex c{T{27}, T{28}}; + + auto [r, i]{c}; + static_assert(std::same_as); + assert(r == T{27}); + static_assert(std::same_as); + assert(i == T{28}); + } + { + std::complex c{T{27}, T{28}}; + + auto& [r, i]{c}; + static_assert(std::same_as); + assert(r == T{27}); + static_assert(std::same_as); + assert(i == T{28}); + } + // `get()` allows using `complex` with ranges + { + std::complex arr[]{{T{27}, T{28}}, {T{82}, T{94}}}; + + std::same_as> decltype(auto) reals{ + arr | std::views::elements<0> | std::ranges::to>()}; + assert(reals.size() == 2); + assert(reals[0] == T{27}); + assert(reals[1] == T{82}); + + std::same_as> decltype(auto) imags{ + arr | std::views::elements<1> | std::ranges::to>()}; + assert(reals.size() == 2); + assert(imags[0] == T{28}); + assert(imags[1] == T{94}); + } +} + +constexpr bool test() { + test(); + test(); + test(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/get.verify.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/get.verify.cpp new file mode 100644 index 000000000000..6a6e3a968d50 --- /dev/null +++ b/libcxx/test/std/numerics/complex.number/complex.tuple/get.verify.cpp @@ -0,0 +1,60 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20, c++23 + +// + +// template +// constexpr T& get(complex&) noexcept; +// template +// constexpr T&& get(complex&&) noexcept; +// template +// constexpr const T& get(const complex&) noexcept; +// template +// constexpr const T&& get(const complex&&) noexcept; + +#include +#include +#include + +template +void test() { + using C = std::complex; + + // & + { + C c{T{27}, T{28}}; + // expected-error-re@*:* 3{{static assertion failed {{.*}}Index value is out of range.}} + std::get<3>(c); + } + // && + { + C c{T{27}, T{28}}; + // expected-error-re@*:* 3 {{static assertion failed {{.*}}Index value is out of range.}} + std::get<3>(std::move(c)); + } + // const & + { + const C c{T{27}, T{28}}; + // expected-error-re@*:* 3 {{static assertion failed {{.*}}Index value is out of range.}} + std::get<3>(c); + } + // const && + { + const C c{T{27}, T{28}}; + // expected-error-re@*:* 3 {{static assertion failed {{.*}}Index value is out of range.}} + std::get<3>(std::move(c)); + } +} + +void test() { + test(); + test(); + test(); +} diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.compile.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.compile.pass.cpp new file mode 100644 index 000000000000..50c0e0eff1ed --- /dev/null +++ b/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.compile.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20, c++23 + +// + +// template struct tuple_element; + +#include +#include +#include + +template +concept HasTupleElement = requires { std::tuple_element{}; }; + +struct SomeObject {}; + +static_assert(!HasTupleElement<0, SomeObject>); +static_assert(!HasTupleElement<1, SomeObject>); +static_assert(!HasTupleElement<3, SomeObject>); + +template +void test() { + using C = std::complex; + + static_assert(HasTupleElement<0, C>); + static_assert(HasTupleElement<1, C>); + + static_assert(std::same_as::type, T>); + static_assert(std::same_as::type, T>); +} + +void test() { + test(); + test(); + test(); +} diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.verify.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.verify.cpp new file mode 100644 index 000000000000..879e2158d091 --- /dev/null +++ b/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.verify.cpp @@ -0,0 +1,31 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20, c++23 + +// + +// template struct tuple_element; + +#include +#include +#include + +template +void test() { + using C = std::complex; + + // expected-error-re@*:* 3 {{static assertion failed {{.*}}Index value is out of range.}} + [[maybe_unused]] std::tuple_element<3, C> te{}; +} + +void test() { + test(); + test(); + test(); +} diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_size.compile.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_size.compile.pass.cpp new file mode 100644 index 000000000000..28dcbe3fc5ec --- /dev/null +++ b/libcxx/test/std/numerics/complex.number/complex.tuple/tuple_size.compile.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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, c++20, c++23 + +// + +// template struct tuple_size; + +#include +#include +#include + +template +concept HasTupleSize = requires { std::tuple_size{}; }; + +struct SomeObject {}; + +static_assert(!HasTupleSize); + +template +void test() { + using C = std::complex; + + static_assert(HasTupleSize); + static_assert(std::same_as::value_type, size_t>); + static_assert(std::tuple_size() == 2); +} + +void test() { + test(); + test(); + test(); +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 9e7ea86f2daa..b688a30cdb79 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -1228,7 +1228,7 @@ feature_test_macros = [ "name": "__cpp_lib_tuple_like", "values": { "c++23": 202207, # P2165R4 Compatibility between tuple, pair and tuple-like objects - "c++26": 202311, # P2819R2 Add tuple protocol to complex + "c++26": 202311, # P2819R2 Add tuple protocol to complex (implemented) }, "headers": ["map", "tuple", "unordered_map", "utility"], "unimplemented": True,