https://github.com/H-G-Hristov updated https://github.com/llvm/llvm-project/pull/79744
>From 52cdb5a5ae4ad33bb16dfe05738d64ee568a24ce Mon Sep 17 00:00:00 2001 From: Zingam <zin...@outlook.com> Date: Sat, 27 Jan 2024 21:12:16 +0200 Subject: [PATCH] [libc++][complex] P2819R2 - Add `tuple` protocol to `complex` Implements: P2819R2 <https://wg21.link/P2819R2> - https://eel.is/c++draft/utilities#concept:tuple-like - https://eel.is/c++draft/complex.syn - https://eel.is/c++draft/complex.tuple --- libcxx/docs/ReleaseNotes/19.rst | 1 + libcxx/docs/Status/Cxx2cPapers.csv | 2 +- libcxx/include/CMakeLists.txt | 1 + libcxx/include/__fwd/complex.h | 25 +++ libcxx/include/__fwd/get.h | 17 +++ libcxx/include/__tuple/tuple_like.h | 8 + libcxx/include/complex | 142 ++++++++++++++++++ libcxx/include/libcxx.imp | 1 + libcxx/include/module.modulemap.in | 2 + libcxx/modules/std/complex.inc | 7 + .../tuple/__tuple_like.compile.pass.cpp | 76 ++++++++++ .../complex.number/complex.tuple/get.pass.cpp | 87 +++++++++++ .../complex.tuple/get.verify.cpp | 60 ++++++++ .../tuple_element.compile.pass.cpp | 43 ++++++ .../complex.tuple/tuple_element.verify.cpp | 31 ++++ .../complex.tuple/tuple_size.compile.pass.cpp | 39 +++++ .../generate_feature_test_macro_components.py | 2 +- 17 files changed, 542 insertions(+), 2 deletions(-) create mode 100644 libcxx/include/__fwd/complex.h create mode 100644 libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp create mode 100644 libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp create mode 100644 libcxx/test/std/numerics/complex.number/complex.tuple/get.verify.cpp create mode 100644 libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.compile.pass.cpp create mode 100644 libcxx/test/std/numerics/complex.number/complex.tuple/tuple_element.verify.cpp create mode 100644 libcxx/test/std/numerics/complex.number/complex.tuple/tuple_size.compile.pass.cpp diff --git a/libcxx/docs/ReleaseNotes/19.rst b/libcxx/docs/ReleaseNotes/19.rst index 17a0415a8ad43..c9faa6f9d456c 100644 --- a/libcxx/docs/ReleaseNotes/19.rst +++ b/libcxx/docs/ReleaseNotes/19.rst @@ -38,6 +38,7 @@ What's New in Libc++ 19.0.0? Implemented Papers ------------------ - P2637R3 - Member ``visit`` +- 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 a62faee4f44e2..1c895f79a4c0f 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -39,7 +39,7 @@ "`P2868R3 <https://wg21.link/P2868R3>`__","LWG","Remove Deprecated ``std::allocator`` Typedef From C++26","Kona November 2023","|Complete|","18.0","" "`P2870R3 <https://wg21.link/P2870R3>`__","LWG","Remove ``basic_string::reserve()`` From C++26","Kona November 2023","|Complete|","18.0","" "`P2871R3 <https://wg21.link/P2871R3>`__","LWG","Remove Deprecated Unicode Conversion Facets from C++26","Kona November 2023","|Complete|","18.0","" -"`P2819R2 <https://wg21.link/P2819R2>`__","LWG","Add tuple protocol to complex","Kona November 2023","","","" +"`P2819R2 <https://wg21.link/P2819R2>`__","LWG","Add tuple protocol to complex","Kona November 2023","|Complete|","19.0","" "`P2937R0 <https://wg21.link/P2937R0>`__","LWG","Freestanding: Remove ``strtok``","Kona November 2023","","","" "`P2833R2 <https://wg21.link/P2833R2>`__","LWG","Freestanding Library: inout expected span","Kona November 2023","","","" "`P2836R1 <https://wg21.link/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 ed721d467e94f..05332a3507d07 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -426,6 +426,7 @@ set(files __functional/weak_result_type.h __fwd/array.h __fwd/bit_reference.h + __fwd/complex.h __fwd/fstream.h __fwd/get.h __fwd/hash.h diff --git a/libcxx/include/__fwd/complex.h b/libcxx/include/__fwd/complex.h new file mode 100644 index 0000000000000..1c7be5a5ff750 --- /dev/null +++ b/libcxx/include/__fwd/complex.h @@ -0,0 +1,25 @@ +//===---------------------------------------------------------------------===// +// +// 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> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template <class _Tp> +class _LIBCPP_TEMPLATE_VIS complex; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___FWD_COMPLEX_H diff --git a/libcxx/include/__fwd/get.h b/libcxx/include/__fwd/get.h index e7261b826953d..dfd2b5ae8d2bb 100644 --- a/libcxx/include/__fwd/get.h +++ b/libcxx/include/__fwd/get.h @@ -12,6 +12,7 @@ #include <__concepts/copyable.h> #include <__config> #include <__fwd/array.h> +#include <__fwd/complex.h> #include <__fwd/pair.h> #include <__fwd/subrange.h> #include <__fwd/tuple.h> @@ -76,6 +77,22 @@ template <size_t _Ip, class _Tp, size_t _Size> _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&& get(const array<_Tp, _Size>&&) _NOEXCEPT; #endif +#if _LIBCPP_STD_VER >= 26 + +template <size_t _Ip, class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp& get(complex<_Tp>&) noexcept; + +template <size_t _Ip, class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr _Tp&& get(complex<_Tp>&&) noexcept; + +template <size_t _Ip, class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& get(const complex<_Tp>&) noexcept; + +template <size_t _Ip, class _Tp> +_LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& get(const complex<_Tp>&&) noexcept; + +#endif // _LIBCPP_STD_VER >= 26 + #if _LIBCPP_STD_VER >= 20 namespace ranges { diff --git a/libcxx/include/__tuple/tuple_like.h b/libcxx/include/__tuple/tuple_like.h index dab395be616b7..0a619e7c99866 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> @@ -41,6 +42,13 @@ struct __tuple_like_impl<array<_Tp, _Size> > : true_type {}; template <class _Ip, class _Sp, ranges::subrange_kind _Kp> struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {}; +# if _LIBCPP_STD_VER >= 26 + +template <class _Tp> +struct __tuple_like_impl<complex<_Tp>> : true_type {}; + +# endif + template <class _Tp> concept __tuple_like = __tuple_like_impl<remove_cvref_t<_Tp>>::value; diff --git a/libcxx/include/complex b/libcxx/include/complex index 02b9db8c516db..a77d18b1f052c 100644 --- a/libcxx/include/complex +++ b/libcxx/include/complex @@ -227,6 +227,31 @@ template<class T> complex<T> sqrt (const complex<T>&); template<class T> complex<T> tan (const complex<T>&); template<class T> complex<T> tanh (const complex<T>&); + // [complex.tuple], tuple interface + template<class T> struct tuple_size; // Since C++26 + template<size_t I, class T> struct tuple_element; // Since C++26 + template<class T> struct tuple_size<complex<T>>; // Since C++26 + template<size_t I, class T> struct tuple_element<I, complex<T>>; // Since C++26 + template<size_t I, class T> + constexpr T& get(complex<T>&) noexcept; // Since C++26 + template<size_t I, class T> + constexpr T&& get(complex<T>&&) noexcept; // Since C++26 + template<size_t I, class T> + constexpr const T& get(const complex<T>&) noexcept; // Since C++26 + template<size_t I, class T> + constexpr const T&& get(const complex<T>&&) noexcept; // Since C++26 + + // [complex.literals], complex literals + inline namespace literals { + inline namespace complex_literals { + constexpr complex<long double> operator""il(long double); // Since C++14 + constexpr complex<long double> operator""il(unsigned long long); // Since C++14 + constexpr complex<double> operator""i(long double); // Since C++14 + constexpr complex<double> operator""i(unsigned long long); // Since C++14 + constexpr complex<float> operator""if(long double); // Since C++14 + constexpr complex<float> operator""if(unsigned long long); // Since C++14 + } + } } // std */ @@ -331,6 +356,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; template <> @@ -408,6 +447,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; template <> @@ -480,6 +533,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; template <> @@ -553,6 +620,20 @@ public: *this = *this / complex(__c.real(), __c.imag()); return *this; } + +#if _LIBCPP_STD_VER >= 26 + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept; + + template <size_t _Ip, class _Xp> + friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept; +#endif }; inline _LIBCPP_CONSTEXPR complex<float>::complex(const complex<double>& __c) : __re_(__c.real()), __im_(__c.imag()) {} @@ -1352,6 +1433,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 <class _Tp> +struct tuple_size; + +template <class _Tp> +struct tuple_size<complex<_Tp>> : integral_constant<size_t, 2> {}; + +template <size_t _Ip, class _Tp> +struct tuple_element; + +template <size_t _Ip, class _Tp> +struct tuple_element<_Ip, complex<_Tp>> { + static_assert(_Ip < 2, "Index value is out of range."); + using type = _Tp; +}; + +template <size_t _Ip, class _Xp> +_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 static_cast<_Xp&>(__z.__re_); + } else { + return static_cast<_Xp&>(__z.__im_); + } +} + +template <size_t _Ip, class _Xp> +_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 static_cast<_Xp&&>(__z.__re_); + } else { + return static_cast<_Xp&&>(__z.__im_); + } +} + +template <size_t _Ip, class _Xp> +_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 static_cast<const _Xp&>(__z.__re_); + } else { + return static_cast<const _Xp&>(__z.__im_); + } +} + +template <size_t _Ip, class _Xp> +_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 static_cast<const _Xp&&>(__z.__re_); + } else { + return static_cast<const _Xp&&>(__z.__im_); + } +} + +#endif // _LIBCPP_STD_VER >= 26 + #if _LIBCPP_STD_VER >= 14 // Literal suffix for complex number literals [complex.literals] inline namespace literals { diff --git a/libcxx/include/libcxx.imp b/libcxx/include/libcxx.imp index 45fa4a9541917..4a6ca1c330280 100644 --- a/libcxx/include/libcxx.imp +++ b/libcxx/include/libcxx.imp @@ -421,6 +421,7 @@ { include: [ "<__fwd/array.h>", "private", "<array>", "public" ] }, { include: [ "<__fwd/bit_reference.h>", "private", "<bitset>", "public" ] }, { include: [ "<__fwd/bit_reference.h>", "private", "<vector>", "public" ] }, + { include: [ "<__fwd/complex.h>", "private", "<complex>", "public" ] }, { include: [ "<__fwd/fstream.h>", "private", "<fstream>", "public" ] }, { include: [ "<__fwd/hash.h>", "private", "<functional>", "public" ] }, { include: [ "<__fwd/ios.h>", "private", "<ios>", "public" ] }, diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 194a74a1e07b1..a5aae481cff54 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -1197,6 +1197,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 3ccf44fa02244..47a44420b127a 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/utilities/tuple/__tuple_like.compile.pass.cpp b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp new file mode 100644 index 0000000000000..9f04f2cc04304 --- /dev/null +++ b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp @@ -0,0 +1,76 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// <tuple> + +#include <array> +#include <complex> +#include <ranges> +#include <tuple> + +#include "test_iterators.h" + +static_assert(!std::__tuple_like<int>); + +static_assert(std::__tuple_like<std::array<int, 0>>); +static_assert(std::__tuple_like<std::array<int, 1>>); +static_assert(std::__tuple_like<std::array<int, 2>>); +static_assert(std::__tuple_like<std::array<int, 2728>>); + +#if _LIBCPP_STD_VER >= 26 +static_assert(std::__tuple_like<std::complex<float>>); +static_assert(std::__tuple_like<std::complex<double>>); +static_assert(std::__tuple_like<std::complex<long double>>); +#endif + +static_assert(std::__tuple_like<std::pair<int, float>>); + +static_assert(std::__tuple_like<std::tuple<int>>); +static_assert(std::__tuple_like<std::tuple<int, float>>); +static_assert(std::__tuple_like<std::tuple<int, float, double>>); + +using FI = forward_iterator<int*>; +static_assert(std::__tuple_like<std::ranges::subrange<FI, FI, std::ranges::subrange_kind::sized>>); +static_assert(std::__tuple_like<std::ranges::subrange<FI, FI, std::ranges::subrange_kind::unsized>>); +static_assert(std::__tuple_like<std::ranges::subrange<int*, int*, std::ranges::subrange_kind::sized>>); +static_assert(std::__tuple_like<std::ranges::subrange<int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>); + +template <typename Iter> +void test_subrange_sized() { + static_assert(std::__tuple_like<std::ranges::subrange<Iter, Iter, std::ranges::subrange_kind::sized>>); +} + +template <typename Iter> +void test_subrange_unsized() { + static_assert(std::__tuple_like<std::ranges::subrange<Iter, Iter, std::ranges::subrange_kind::unsized>>); +} + +void test() { + test_subrange_sized<forward_iterator<int*>>(); + test_subrange_sized<bidirectional_iterator<int*>>(); + test_subrange_sized<random_access_iterator<int*>>(); + test_subrange_sized<contiguous_iterator<int*>>(); + test_subrange_sized<int*>(); + + test_subrange_sized<forward_iterator<int const*>>(); + test_subrange_sized<bidirectional_iterator<int const*>>(); + test_subrange_sized<random_access_iterator<int const*>>(); + test_subrange_sized<contiguous_iterator<int const*>>(); + test_subrange_sized<int const*>(); + + test_subrange_unsized<forward_iterator<int*>>(); + test_subrange_unsized<bidirectional_iterator<int*>>(); + static_assert(std::__tuple_like<std::ranges::subrange<int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>); + + test_subrange_unsized<forward_iterator<int const*>>(); + test_subrange_unsized<bidirectional_iterator<int const*>>(); + static_assert( + std::__tuple_like<std::ranges::subrange<const int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>); +} 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 0000000000000..0ada5c71777a7 --- /dev/null +++ b/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp @@ -0,0 +1,87 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// <complex> + +// template<size_t I, class T> +// constexpr T& get(complex<T>&) noexcept; +// template<size_t I, class T> +// constexpr T&& get(complex<T>&&) noexcept; +// template<size_t I, class T> +// constexpr const T& get(const complex<T>&) noexcept; +// template<size_t I, class T> +// constexpr const T&& get(const complex<T>&&) noexcept; + +#include <cassert> +#include <concepts> +#include <complex> +#include <utility> + +template <typename T> +constexpr void test() { + // & + { + std::complex<T> c{T{27}, T{28}}; + + std::same_as<T&> decltype(auto) r = get<0>(c); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + std::same_as<T&> decltype(auto) i = get<1>(c); + static_assert(noexcept(get<1>(c))); + assert(i == T{28}); + } + // && + { + std::complex<T> c{T{27}, T{28}}; + + std::same_as<T&&> decltype(auto) r = get<0>(std::move(c)); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + std::same_as<T&&> decltype(auto) i = get<1>(std::move(c)); + assert(i == T{28}); + } + // const & + { + const std::complex<T> c{T{27}, T{28}}; + + std::same_as<const T&> decltype(auto) r = get<0>(c); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + std::same_as<const T&> decltype(auto) i = get<1>(c); + static_assert(noexcept(get<1>(c))); + assert(i == T{28}); + } + // const && + { + const std::complex<T> c{T{27}, T{28}}; + + std::same_as<const T&&> decltype(auto) r = get<0>(std::move(c)); + static_assert(noexcept(get<0>(c))); + assert(r == T{27}); + std::same_as<const T&&> decltype(auto) i = get<1>(std::move(c)); + static_assert(noexcept(get<1>(c))); + assert(i == T{28}); + } +} + +constexpr bool test() { + test<float>(); + test<double>(); + test<long double>(); + + 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 0000000000000..6a6e3a968d50f --- /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 + +// <complex> + +// template<size_t I, class T> +// constexpr T& get(complex<T>&) noexcept; +// template<size_t I, class T> +// constexpr T&& get(complex<T>&&) noexcept; +// template<size_t I, class T> +// constexpr const T& get(const complex<T>&) noexcept; +// template<size_t I, class T> +// constexpr const T&& get(const complex<T>&&) noexcept; + +#include <cassert> +#include <complex> +#include <utility> + +template <typename T> +void test() { + using C = std::complex<T>; + + // & + { + 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<float>(); + test<double>(); + test<long double>(); +} 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 0000000000000..896af798efa20 --- /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 + +// <complex> + +// template<size_t I, class T> struct tuple_element; + +#include <cassert> +#include <concepts> +#include <complex> + +template <size_t I, typename C> +concept HasTupleElement = requires { std::tuple_element<I, C>{}; }; + +struct SomeObject {}; + +static_assert(!HasTupleElement<0, SomeObject>); +static_assert(!HasTupleElement<1, SomeObject>); +static_assert(!HasTupleElement<3, SomeObject>); + +template <typename T> +void test() { + using C = std::complex<T>; + + static_assert(HasTupleElement<0, C>); + static_assert(HasTupleElement<1, C>); + + static_assert(std::same_as<typename std::tuple_element<0, C>::type, T>); + static_assert(std::same_as<typename std::tuple_element<1, C>::type, T>); +} + +void test() { + test<float>(); + test<double>(); + test<long double>(); +} 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 0000000000000..3fab9e94b0005 --- /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 + +// <complex> + +// template<size_t I, class T> struct tuple_element; + +#include <cassert> +#include <concepts> +#include <complex> + +template <typename T> +void test() { + using C = std::complex<T>; + + // expected-error-re@*:* 3 {{static assertion failed {{.*}}Index value is out of range.}} + [[maybe_unused]] std::tuple_element<3, C> te{}; +} + +void test() { + test<float>(); + test<double>(); + test<long double>(); +} 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 0000000000000..6812680445511 --- /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 + +// <complex> + +// template<class T> struct tuple_size; + +#include <cassert> +#include <concepts> +#include <complex> + +template <typename C> +concept HasTupleSize = requires { std::tuple_size<C>{}; }; + +struct SomeObject {}; + +static_assert(!HasTupleSize<SomeObject>); + +template <typename T> +void test() { + using C = std::complex<T>; + + static_assert(HasTupleSize<C>); + static_assert(std::same_as<typename std::tuple_size<C>::value_type, size_t>); + static_assert(std::tuple_size<C>() == 2); +} + +void test() { + test<float>(); + test<double>(); + test<long double>(); +} diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index 065b70620cd17..1408fd51c364c 100755 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -1223,7 +1223,7 @@ def add_version_header(tc): "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, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits