[libcxx-commits] [libcxx] [libc++][complex] P2819R2: Add `tuple` protocol to `complex` (PR #79744)
Hristo Hristov via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Feb 13 02:38:51 PST 2024
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 <zingam at outlook.com>
Date: Sat, 27 Jan 2024 21:12:16 +0200
Subject: [PATCH 1/6] [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 17a0415a8ad436..c9faa6f9d456c6 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 a62faee4f44e22..1c895f79a4c0f1 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 ed721d467e94f4..05332a3507d07a 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 00000000000000..1c7be5a5ff7502
--- /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 e7261b826953d7..dfd2b5ae8d2bbd 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 dab395be616b7d..0a619e7c998666 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 02b9db8c516db4..a77d18b1f052c6 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 45fa4a9541917f..4a6ca1c330280f 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 194a74a1e07b14..a5aae481cff54e 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 3ccf44fa022443..47a44420b127a9 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 00000000000000..9f04f2cc04304b
--- /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 00000000000000..0ada5c71777a72
--- /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 00000000000000..6a6e3a968d50f7
--- /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 00000000000000..896af798efa205
--- /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 00000000000000..3fab9e94b0005f
--- /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 00000000000000..68126804455110
--- /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 065b70620cd170..1408fd51c364c5 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,
>From d04435fde0d7c9b9ed89c38b559daf7eac8cd80d Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Mon, 12 Feb 2024 12:18:14 +0200
Subject: [PATCH 2/6] Moved `get` to `complex.h`
---
libcxx/include/__fwd/complex.h | 17 +++++++++++++++++
libcxx/include/__fwd/get.h | 17 -----------------
2 files changed, 17 insertions(+), 17 deletions(-)
diff --git a/libcxx/include/__fwd/complex.h b/libcxx/include/__fwd/complex.h
index 1c7be5a5ff7502..22c78c5cc3c77a 100644
--- a/libcxx/include/__fwd/complex.h
+++ b/libcxx/include/__fwd/complex.h
@@ -10,6 +10,7 @@
#define _LIBCPP___FWD_COMPLEX_H
#include <__config>
+#include <cstddef>
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
@@ -20,6 +21,22 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp>
class _LIBCPP_TEMPLATE_VIS complex;
+#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
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___FWD_COMPLEX_H
diff --git a/libcxx/include/__fwd/get.h b/libcxx/include/__fwd/get.h
index dfd2b5ae8d2bbd..e7261b826953d7 100644
--- a/libcxx/include/__fwd/get.h
+++ b/libcxx/include/__fwd/get.h
@@ -12,7 +12,6 @@
#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>
@@ -77,22 +76,6 @@ 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 {
>From c5bceaea10211784c3390b9f508d0d3a4ed0961a Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 13 Feb 2024 10:45:35 +0200
Subject: [PATCH 3/6] Addressed comments
---
libcxx/include/complex | 33 +++++---
.../tuple/__tuple_like.compile.pass.cpp | 18 +++++
.../complex.tuple/general.pass.cpp | 80 +++++++++++++++++++
.../complex.number/complex.tuple/get.pass.cpp | 9 +++
4 files changed, 128 insertions(+), 12 deletions(-)
create mode 100644 libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
diff --git a/libcxx/include/complex b/libcxx/include/complex
index a77d18b1f052c6..acf73f2fb12ae8 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -228,18 +228,18 @@ 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<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
+ constexpr T& get(complex<T>&) noexcept; // Since C++26
template<size_t I, class T>
- constexpr T&& get(complex<T>&&) noexcept; // Since C++26
+ 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
+ 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
+ constexpr const T&& get(const complex<T>&&) noexcept; // Since C++26
// [complex.literals], complex literals
inline namespace literals {
@@ -258,6 +258,10 @@ template<class T> complex<T> tanh (const complex<T>&);
#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 <cmath>
#include <version>
@@ -269,6 +273,9 @@ template<class T> complex<T> tanh (const complex<T>&);
# pragma GCC system_header
#endif
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
_LIBCPP_BEGIN_NAMESPACE_STD
template <class _Tp>
@@ -1466,9 +1473,9 @@ 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_);
+ return std::move(__z.__re_);
} else {
- return static_cast<_Xp&&>(__z.__im_);
+ return std::move(__z.__im_);
}
}
@@ -1486,9 +1493,9 @@ 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_);
+ return std::move(__z.__re_);
} else {
- return static_cast<const _Xp&&>(__z.__im_);
+ return std::move(__z.__im_);
}
}
@@ -1525,6 +1532,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr complex<float> operator""if(unsigned long
_LIBCPP_END_NAMESPACE_STD
+_LIBCPP_POP_MACROS
+
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
# include <iosfwd>
# include <stdexcept>
diff --git a/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp
index 9f04f2cc04304b..3f9dcfe299c224 100644
--- a/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp
@@ -10,6 +10,12 @@
// <tuple>
+// 22.4.3 Concept `tuple-like` [tuple.like]
+//
+// template<class T>
+// concept tuple-like; // exposition only
+
+
#include <array>
#include <complex>
#include <ranges>
@@ -17,25 +23,37 @@
#include "test_iterators.h"
+// Non-tuple-like type
+
static_assert(!std::__tuple_like<int>);
+// Tuple-like: array
+
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>>);
+// Tuple-like: complex
+
#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
+// Tuple-like: pair
+
static_assert(std::__tuple_like<std::pair<int, float>>);
+// Tuple-like: tuple
+
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>>);
+// Support for <ranges>
+
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>>);
diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
new file mode 100644
index 00000000000000..cb05703d89d031
--- /dev/null
+++ b/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
@@ -0,0 +1,80 @@
+//===----------------------------------------------------------------------===//
+//
+// 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() {
+ // Structured binding
+
+ // &
+ {
+ std::complex<T> c{T{27}, T{28}};
+
+ auto& [r, i]{c};
+ assert(r == T{27});
+ assert(i == T{28});
+ }
+ // &&
+ {
+ std::complex<T> c{T{27}, T{28}};
+
+ auto&& [r, i]{std::move(c)};
+ assert(r == T{27});
+ assert(i == T{28});
+ }
+ // const &
+ {
+ const std::complex<T> c{T{27}, T{28}};
+
+ const auto& [r, i]{c};
+ assert(r == T{27});
+ assert(i == T{28});
+ }
+ // const &&
+ {
+ const std::complex<T> c{T{27}, T{28}};
+
+ const auto&& [r, i]{std::move(c)};
+ assert(r == T{27});
+ assert(i == T{28});
+ }
+
+ // Ranges
+}
+
+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.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp
index 0ada5c71777a72..d1a4583819e2cf 100644
--- a/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp
@@ -44,7 +44,12 @@ constexpr void test() {
std::same_as<T&&> decltype(auto) r = get<0>(std::move(c));
static_assert(noexcept(get<0>(c)));
assert(r == T{27});
+ }
+ {
+ std::complex<T> c{T{27}, T{28}};
+
std::same_as<T&&> decltype(auto) i = get<1>(std::move(c));
+ static_assert(noexcept(get<1>(c)));
assert(i == T{28});
}
// const &
@@ -65,6 +70,10 @@ constexpr void test() {
std::same_as<const T&&> decltype(auto) r = get<0>(std::move(c));
static_assert(noexcept(get<0>(c)));
assert(r == T{27});
+ }
+ {
+ const std::complex<T> c{T{27}, T{28}};
+
std::same_as<const T&&> decltype(auto) i = get<1>(std::move(c));
static_assert(noexcept(get<1>(c)));
assert(i == T{28});
>From e0c5d047116e1cece308055fa60c07c43b77e94a Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 13 Feb 2024 12:29:19 +0200
Subject: [PATCH 4/6] Try to fix CI
---
.../test/libcxx/transitive_includes/cxx03.csv | 5 ++++
.../test/libcxx/transitive_includes/cxx11.csv | 1 +
.../test/libcxx/transitive_includes/cxx14.csv | 1 +
.../test/libcxx/transitive_includes/cxx17.csv | 1 +
.../test/libcxx/transitive_includes/cxx20.csv | 1 +
.../test/libcxx/transitive_includes/cxx23.csv | 1 +
.../test/libcxx/transitive_includes/cxx26.csv | 1 +
.../tuple/__tuple_like.compile.pass.cpp | 1 -
.../complex.tuple/general.pass.cpp | 27 +++++++++++++------
9 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/libcxx/test/libcxx/transitive_includes/cxx03.csv b/libcxx/test/libcxx/transitive_includes/cxx03.csv
index c65c65449f4e07..45efc6c6664dfc 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx03.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx03.csv
@@ -158,6 +158,7 @@ compare limits
compare type_traits
compare version
complex cmath
+complex cstddef
complex iosfwd
complex sstream
complex stdexcept
@@ -834,13 +835,17 @@ system_error type_traits
system_error version
thread array
thread atomic
+thread cctype
thread cerrno
thread chrono
+thread clocale
thread compare
thread cstddef
thread cstdint
+thread cstdlib
thread cstring
thread ctime
+thread cwchar
thread functional
thread iosfwd
thread limits
diff --git a/libcxx/test/libcxx/transitive_includes/cxx11.csv b/libcxx/test/libcxx/transitive_includes/cxx11.csv
index e9eae06807e6b8..1358f360c754af 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx11.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx11.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/cxx14.csv b/libcxx/test/libcxx/transitive_includes/cxx14.csv
index 08db2a0ea6b1a0..8f2737b617c971 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx14.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx14.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/cxx17.csv b/libcxx/test/libcxx/transitive_includes/cxx17.csv
index 08db2a0ea6b1a0..8f2737b617c971 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx17.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx17.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/cxx20.csv b/libcxx/test/libcxx/transitive_includes/cxx20.csv
index 69805d6af3e94e..170a833418e01e 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx20.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx20.csv
@@ -165,6 +165,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 f9957897c743ac..42112f7dd69ccb 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx23.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx23.csv
@@ -110,6 +110,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 f9957897c743ac..42112f7dd69ccb 100644
--- a/libcxx/test/libcxx/transitive_includes/cxx26.csv
+++ b/libcxx/test/libcxx/transitive_includes/cxx26.csv
@@ -110,6 +110,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
index 3f9dcfe299c224..b1d199865decc1 100644
--- a/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp
+++ b/libcxx/test/libcxx/utilities/tuple/__tuple_like.compile.pass.cpp
@@ -15,7 +15,6 @@
// template<class T>
// concept tuple-like; // exposition only
-
#include <array>
#include <complex>
#include <ranges>
diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
index cb05703d89d031..ca816336c8576c 100644
--- a/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
@@ -10,18 +10,15 @@
// <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;
+// Support for:
+// - Structured bindings
+// - Ranges
#include <cassert>
#include <concepts>
#include <complex>
+#include <ranges>
+
#include <utility>
template <typename T>
@@ -62,6 +59,20 @@ constexpr void test() {
}
// Ranges
+
+ {
+ std::complex<T> arr[]{{27, 28}, {82, 94}};
+
+ std::same_as<std::vector<T>> decltype(auto) reals{arr | std::views::elements<0> | std::ranges::to<std::vector>()};
+ assert(reals.size() == 2);
+ assert(reals[0] == 27);
+ assert(reals[1] == 82);
+
+ std::same_as<std::vector<T>> decltype(auto) imags{arr | std::views::elements<1> | std::ranges::to<std::vector>()};
+ assert(reals.size() == 2);
+ assert(imags[0] == 28);
+ assert(imags[1] == 94);
+ }
}
constexpr bool test() {
>From ada32afbc17a3e6e2201a4e897b151334f093962 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 13 Feb 2024 12:33:46 +0200
Subject: [PATCH 5/6] Cleanup
---
libcxx/include/complex | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libcxx/include/complex b/libcxx/include/complex
index acf73f2fb12ae8..0aba60e514ba22 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -1463,9 +1463,9 @@ 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_);
+ return __z.__re_;
} else {
- return static_cast<_Xp&>(__z.__im_);
+ return __z.__im_;
}
}
@@ -1483,9 +1483,9 @@ 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_);
+ return __z.__re_;
} else {
- return static_cast<const _Xp&>(__z.__im_);
+ return __z.__im_;
}
}
>From fd06775af4f7cf613f27bb90712c770bd8e21023 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <hghristov.rmm at gmail.com>
Date: Tue, 13 Feb 2024 12:38:19 +0200
Subject: [PATCH 6/6] Fixed formatting
---
.../numerics/complex.number/complex.tuple/general.pass.cpp | 4 ++--
.../std/numerics/complex.number/complex.tuple/get.pass.cpp | 2 +-
.../complex.tuple/tuple_element.compile.pass.cpp | 2 +-
.../complex.number/complex.tuple/tuple_element.verify.cpp | 2 +-
.../complex.number/complex.tuple/tuple_size.compile.pass.cpp | 2 +-
5 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp b/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
index ca816336c8576c..ab860546dca40c 100644
--- a/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.tuple/general.pass.cpp
@@ -15,11 +15,11 @@
// - Ranges
#include <cassert>
-#include <concepts>
#include <complex>
+#include <concepts>
#include <ranges>
-
#include <utility>
+#include <vector>
template <typename T>
constexpr void test() {
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
index d1a4583819e2cf..bc6100ba16e150 100644
--- a/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp
+++ b/libcxx/test/std/numerics/complex.number/complex.tuple/get.pass.cpp
@@ -20,8 +20,8 @@
// constexpr const T&& get(const complex<T>&&) noexcept;
#include <cassert>
-#include <concepts>
#include <complex>
+#include <concepts>
#include <utility>
template <typename T>
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
index 896af798efa205..50c0e0eff1eda8 100644
--- 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
@@ -13,8 +13,8 @@
// template<size_t I, class T> struct tuple_element;
#include <cassert>
-#include <concepts>
#include <complex>
+#include <concepts>
template <size_t I, typename C>
concept HasTupleElement = requires { std::tuple_element<I, C>{}; };
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
index 3fab9e94b0005f..879e2158d09129 100644
--- 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
@@ -13,8 +13,8 @@
// template<size_t I, class T> struct tuple_element;
#include <cassert>
-#include <concepts>
#include <complex>
+#include <concepts>
template <typename T>
void 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
index 68126804455110..28dcbe3fc5ecdf 100644
--- 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
@@ -13,8 +13,8 @@
// template<class T> struct tuple_size;
#include <cassert>
-#include <concepts>
#include <complex>
+#include <concepts>
template <typename C>
concept HasTupleSize = requires { std::tuple_size<C>{}; };
More information about the libcxx-commits
mailing list