Skip to content

Commit 2ea5d16

Browse files
H-G-HristovZingam
andauthored
[libc++][complex] P2819R2: Add tuple protocol to complex (llvm#79744)
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 --------- Co-authored-by: Zingam <[email protected]>
1 parent 9d3d6ec commit 2ea5d16

24 files changed

+622
-2
lines changed

libcxx/docs/ReleaseNotes/19.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Implemented Papers
4040

4141
- P2637R3 - Member ``visit``
4242
- P2652R2 - Disallow User Specialization of ``allocator_traits``
43+
- P2819R2 - Add ``tuple`` protocol to ``complex``
4344

4445

4546
Improvements and New Features

libcxx/docs/Status/Cxx2cPapers.csv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"`P2868R3 <https://wg21.link/P2868R3>`__","LWG","Remove Deprecated ``std::allocator`` Typedef From C++26","Kona November 2023","|Complete|","18.0",""
4040
"`P2870R3 <https://wg21.link/P2870R3>`__","LWG","Remove ``basic_string::reserve()`` From C++26","Kona November 2023","|Complete|","18.0",""
4141
"`P2871R3 <https://wg21.link/P2871R3>`__","LWG","Remove Deprecated Unicode Conversion Facets from C++26","Kona November 2023","|Complete|","18.0",""
42-
"`P2819R2 <https://wg21.link/P2819R2>`__","LWG","Add tuple protocol to complex","Kona November 2023","","",""
42+
"`P2819R2 <https://wg21.link/P2819R2>`__","LWG","Add tuple protocol to complex","Kona November 2023","|Complete|","19.0",""
4343
"`P2937R0 <https://wg21.link/P2937R0>`__","LWG","Freestanding: Remove ``strtok``","Kona November 2023","","",""
4444
"`P2833R2 <https://wg21.link/P2833R2>`__","LWG","Freestanding Library: inout expected span","Kona November 2023","","",""
4545
"`P2836R1 <https://wg21.link/P2836R1>`__","LWG","``std::basic_const_iterator`` should follow its underlying type's convertibility","Kona November 2023","","","|DR|"

libcxx/include/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ set(files
429429
__functional/weak_result_type.h
430430
__fwd/array.h
431431
__fwd/bit_reference.h
432+
__fwd/complex.h
432433
__fwd/fstream.h
433434
__fwd/hash.h
434435
__fwd/ios.h

libcxx/include/__fwd/complex.h

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//===---------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===---------------------------------------------------------------------===//
8+
9+
#ifndef _LIBCPP___FWD_COMPLEX_H
10+
#define _LIBCPP___FWD_COMPLEX_H
11+
12+
#include <__config>
13+
#include <cstddef>
14+
15+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16+
# pragma GCC system_header
17+
#endif
18+
19+
_LIBCPP_BEGIN_NAMESPACE_STD
20+
21+
template <class _Tp>
22+
class _LIBCPP_TEMPLATE_VIS complex;
23+
24+
#if _LIBCPP_STD_VER >= 26
25+
26+
template <size_t _Ip, class _Tp>
27+
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& get(complex<_Tp>&) noexcept;
28+
29+
template <size_t _Ip, class _Tp>
30+
_LIBCPP_HIDE_FROM_ABI constexpr _Tp&& get(complex<_Tp>&&) noexcept;
31+
32+
template <size_t _Ip, class _Tp>
33+
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& get(const complex<_Tp>&) noexcept;
34+
35+
template <size_t _Ip, class _Tp>
36+
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& get(const complex<_Tp>&&) noexcept;
37+
38+
#endif // _LIBCPP_STD_VER >= 26
39+
40+
_LIBCPP_END_NAMESPACE_STD
41+
42+
#endif // _LIBCPP___FWD_COMPLEX_H

libcxx/include/__ranges/elements_view.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <__concepts/derived_from.h>
1717
#include <__concepts/equality_comparable.h>
1818
#include <__config>
19+
#include <__fwd/complex.h>
1920
#include <__iterator/concepts.h>
2021
#include <__iterator/iterator_traits.h>
2122
#include <__ranges/access.h>

libcxx/include/__tuple/tuple_like.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <__config>
1313
#include <__fwd/array.h>
14+
#include <__fwd/complex.h>
1415
#include <__fwd/pair.h>
1516
#include <__fwd/subrange.h>
1617
#include <__fwd/tuple.h>
@@ -40,6 +41,13 @@ struct __tuple_like_impl<array<_Tp, _Size> > : true_type {};
4041
template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
4142
struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {};
4243

44+
# if _LIBCPP_STD_VER >= 26
45+
46+
template <class _Tp>
47+
struct __tuple_like_impl<complex<_Tp>> : true_type {};
48+
49+
# endif
50+
4351
template <class _Tp>
4452
concept __tuple_like = __tuple_like_impl<remove_cvref_t<_Tp>>::value;
4553

libcxx/include/complex

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,12 +227,41 @@ template<class T> complex<T> sqrt (const complex<T>&);
227227
template<class T> complex<T> tan (const complex<T>&);
228228
template<class T> complex<T> tanh (const complex<T>&);
229229
230+
// [complex.tuple], tuple interface
231+
template<class T> struct tuple_size; // Since C++26
232+
template<size_t I, class T> struct tuple_element; // Since C++26
233+
template<class T> struct tuple_size<complex<T>>; // Since C++26
234+
template<size_t I, class T> struct tuple_element<I, complex<T>>; // Since C++26
235+
template<size_t I, class T>
236+
constexpr T& get(complex<T>&) noexcept; // Since C++26
237+
template<size_t I, class T>
238+
constexpr T&& get(complex<T>&&) noexcept; // Since C++26
239+
template<size_t I, class T>
240+
constexpr const T& get(const complex<T>&) noexcept; // Since C++26
241+
template<size_t I, class T>
242+
constexpr const T&& get(const complex<T>&&) noexcept; // Since C++26
243+
244+
// [complex.literals], complex literals
245+
inline namespace literals {
246+
inline namespace complex_literals {
247+
constexpr complex<long double> operator""il(long double); // Since C++14
248+
constexpr complex<long double> operator""il(unsigned long long); // Since C++14
249+
constexpr complex<double> operator""i(long double); // Since C++14
250+
constexpr complex<double> operator""i(unsigned long long); // Since C++14
251+
constexpr complex<float> operator""if(long double); // Since C++14
252+
constexpr complex<float> operator""if(unsigned long long); // Since C++14
253+
}
254+
}
230255
} // std
231256
232257
*/
233258

234259
#include <__assert> // all public C++ headers provide the assertion handler
235260
#include <__config>
261+
#include <__fwd/complex.h>
262+
#include <__tuple/tuple_element.h>
263+
#include <__tuple/tuple_size.h>
264+
#include <__utility/move.h>
236265
#include <cmath>
237266
#include <version>
238267

@@ -244,6 +273,9 @@ template<class T> complex<T> tanh (const complex<T>&);
244273
# pragma GCC system_header
245274
#endif
246275

276+
_LIBCPP_PUSH_MACROS
277+
#include <__undef_macros>
278+
247279
_LIBCPP_BEGIN_NAMESPACE_STD
248280

249281
template <class _Tp>
@@ -331,6 +363,20 @@ public:
331363
*this = *this / complex(__c.real(), __c.imag());
332364
return *this;
333365
}
366+
367+
#if _LIBCPP_STD_VER >= 26
368+
template <size_t _Ip, class _Xp>
369+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
370+
371+
template <size_t _Ip, class _Xp>
372+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
373+
374+
template <size_t _Ip, class _Xp>
375+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
376+
377+
template <size_t _Ip, class _Xp>
378+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
379+
#endif
334380
};
335381

336382
template <>
@@ -408,6 +454,20 @@ public:
408454
*this = *this / complex(__c.real(), __c.imag());
409455
return *this;
410456
}
457+
458+
#if _LIBCPP_STD_VER >= 26
459+
template <size_t _Ip, class _Xp>
460+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
461+
462+
template <size_t _Ip, class _Xp>
463+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
464+
465+
template <size_t _Ip, class _Xp>
466+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
467+
468+
template <size_t _Ip, class _Xp>
469+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
470+
#endif
411471
};
412472

413473
template <>
@@ -480,6 +540,20 @@ public:
480540
*this = *this / complex(__c.real(), __c.imag());
481541
return *this;
482542
}
543+
544+
#if _LIBCPP_STD_VER >= 26
545+
template <size_t _Ip, class _Xp>
546+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
547+
548+
template <size_t _Ip, class _Xp>
549+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
550+
551+
template <size_t _Ip, class _Xp>
552+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
553+
554+
template <size_t _Ip, class _Xp>
555+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
556+
#endif
483557
};
484558

485559
template <>
@@ -553,6 +627,20 @@ public:
553627
*this = *this / complex(__c.real(), __c.imag());
554628
return *this;
555629
}
630+
631+
#if _LIBCPP_STD_VER >= 26
632+
template <size_t _Ip, class _Xp>
633+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
634+
635+
template <size_t _Ip, class _Xp>
636+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
637+
638+
template <size_t _Ip, class _Xp>
639+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
640+
641+
template <size_t _Ip, class _Xp>
642+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
643+
#endif
556644
};
557645

558646
inline _LIBCPP_CONSTEXPR complex<float>::complex(const complex<double>& __c) : __re_(__c.real()), __im_(__c.imag()) {}
@@ -1352,6 +1440,67 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) {
13521440
}
13531441
#endif // !_LIBCPP_HAS_NO_LOCALIZATION
13541442

1443+
#if _LIBCPP_STD_VER >= 26
1444+
1445+
// [complex.tuple], tuple interface
1446+
1447+
template <class _Tp>
1448+
struct tuple_size;
1449+
1450+
template <class _Tp>
1451+
struct tuple_size<complex<_Tp>> : integral_constant<size_t, 2> {};
1452+
1453+
template <size_t _Ip, class _Tp>
1454+
struct tuple_element;
1455+
1456+
template <size_t _Ip, class _Tp>
1457+
struct tuple_element<_Ip, complex<_Tp>> {
1458+
static_assert(_Ip < 2, "Index value is out of range.");
1459+
using type = _Tp;
1460+
};
1461+
1462+
template <size_t _Ip, class _Xp>
1463+
_LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>& __z) noexcept {
1464+
static_assert(_Ip < 2, "Index value is out of range.");
1465+
if constexpr (_Ip == 0) {
1466+
return __z.__re_;
1467+
} else {
1468+
return __z.__im_;
1469+
}
1470+
}
1471+
1472+
template <size_t _Ip, class _Xp>
1473+
_LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&& __z) noexcept {
1474+
static_assert(_Ip < 2, "Index value is out of range.");
1475+
if constexpr (_Ip == 0) {
1476+
return std::move(__z.__re_);
1477+
} else {
1478+
return std::move(__z.__im_);
1479+
}
1480+
}
1481+
1482+
template <size_t _Ip, class _Xp>
1483+
_LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>& __z) noexcept {
1484+
static_assert(_Ip < 2, "Index value is out of range.");
1485+
if constexpr (_Ip == 0) {
1486+
return __z.__re_;
1487+
} else {
1488+
return __z.__im_;
1489+
}
1490+
}
1491+
1492+
template <size_t _Ip, class _Xp>
1493+
_LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&& __z) noexcept {
1494+
static_assert(_Ip < 2, "Index value is out of range.");
1495+
if constexpr (_Ip == 0) {
1496+
return std::move(__z.__re_);
1497+
} else {
1498+
return std::move(__z.__im_);
1499+
}
1500+
}
1501+
1502+
#endif // _LIBCPP_STD_VER >= 26
1503+
13551504
#if _LIBCPP_STD_VER >= 14
13561505
// Literal suffix for complex number literals [complex.literals]
13571506
inline namespace literals {
@@ -1383,6 +1532,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr complex<float> operator""if(unsigned long
13831532

13841533
_LIBCPP_END_NAMESPACE_STD
13851534

1535+
_LIBCPP_POP_MACROS
1536+
13861537
#if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
13871538
# include <iosfwd>
13881539
# include <stdexcept>

libcxx/include/libcxx.imp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@
424424
{ include: [ "<__fwd/array.h>", "private", "<array>", "public" ] },
425425
{ include: [ "<__fwd/bit_reference.h>", "private", "<bitset>", "public" ] },
426426
{ include: [ "<__fwd/bit_reference.h>", "private", "<vector>", "public" ] },
427+
{ include: [ "<__fwd/complex.h>", "private", "<complex>", "public" ] },
427428
{ include: [ "<__fwd/fstream.h>", "private", "<fstream>", "public" ] },
428429
{ include: [ "<__fwd/hash.h>", "private", "<functional>", "public" ] },
429430
{ include: [ "<__fwd/ios.h>", "private", "<ios>", "public" ] },

libcxx/include/module.modulemap.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,8 @@ module std_private_compare_synth_three_way [system] { header "__c
11951195
module std_private_compare_three_way_comparable [system] { header "__compare/three_way_comparable.h" }
11961196
module std_private_compare_weak_order [system] { header "__compare/weak_order.h" }
11971197

1198+
module std_private_complex_complex_fwd [system] { header "__fwd/complex.h" }
1199+
11981200
module std_private_concepts_arithmetic [system] { header "__concepts/arithmetic.h" }
11991201
module std_private_concepts_assignable [system] { header "__concepts/assignable.h" }
12001202
module std_private_concepts_boolean_testable [system] { header "__concepts/boolean_testable.h" }

libcxx/modules/std/complex.inc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,13 @@ export namespace std {
5959
using std::tan;
6060
using std::tanh;
6161

62+
#if _LIBCPP_STD_VER >= 26
63+
// [complex.tuple], tuple interface
64+
using std::get;
65+
using std::tuple_element;
66+
using std::tuple_size;
67+
#endif
68+
6269
// [complex.literals], complex literals
6370
inline namespace literals {
6471
inline namespace complex_literals {

libcxx/test/libcxx/transitive_includes/cxx03.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ compare limits
159159
compare type_traits
160160
compare version
161161
complex cmath
162+
complex cstddef
162163
complex iosfwd
163164
complex sstream
164165
complex stdexcept

libcxx/test/libcxx/transitive_includes/cxx11.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ compare limits
160160
compare type_traits
161161
compare version
162162
complex cmath
163+
complex cstddef
163164
complex iosfwd
164165
complex sstream
165166
complex stdexcept

libcxx/test/libcxx/transitive_includes/cxx14.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ compare limits
160160
compare type_traits
161161
compare version
162162
complex cmath
163+
complex cstddef
163164
complex iosfwd
164165
complex sstream
165166
complex stdexcept

libcxx/test/libcxx/transitive_includes/cxx17.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ compare limits
160160
compare type_traits
161161
compare version
162162
complex cmath
163+
complex cstddef
163164
complex iosfwd
164165
complex sstream
165166
complex stdexcept

libcxx/test/libcxx/transitive_includes/cxx20.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,7 @@ compare limits
166166
compare type_traits
167167
compare version
168168
complex cmath
169+
complex cstddef
169170
complex iosfwd
170171
complex sstream
171172
complex stdexcept

libcxx/test/libcxx/transitive_includes/cxx23.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ compare cstdint
111111
compare limits
112112
compare version
113113
complex cmath
114+
complex cstddef
114115
complex sstream
115116
complex version
116117
concepts cstddef

libcxx/test/libcxx/transitive_includes/cxx26.csv

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ compare cstdint
111111
compare limits
112112
compare version
113113
complex cmath
114+
complex cstddef
114115
complex sstream
115116
complex version
116117
concepts cstddef

0 commit comments

Comments
 (0)