Skip to content

Commit 361d25b

Browse files
committed
1 parent 74e5418 commit 361d25b

File tree

17 files changed

+542
-3
lines changed

17 files changed

+542
-3
lines changed

libcxx/docs/ReleaseNotes/19.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ see the `releases page <https://llvm.org/releases/>`_.
3535
What's New in Libc++ 19.0.0?
3636
==============================
3737

38-
TODO
38+
P2819R2 - Add ``tuple`` protocol to ``complex``
3939

4040

4141
Implemented Papers

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
@@ -426,6 +426,7 @@ set(files
426426
__functional/weak_result_type.h
427427
__fwd/array.h
428428
__fwd/bit_reference.h
429+
__fwd/complex.h
429430
__fwd/fstream.h
430431
__fwd/get.h
431432
__fwd/hash.h

libcxx/include/__fwd/complex.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
14+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
15+
# pragma GCC system_header
16+
#endif
17+
18+
_LIBCPP_BEGIN_NAMESPACE_STD
19+
20+
template <class _Tp>
21+
class _LIBCPP_TEMPLATE_VIS complex;
22+
23+
_LIBCPP_END_NAMESPACE_STD
24+
25+
#endif // _LIBCPP___FWD_COMPLEX_H

libcxx/include/__fwd/get.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <__concepts/copyable.h>
1313
#include <__config>
1414
#include <__fwd/array.h>
15+
#include <__fwd/complex.h>
1516
#include <__fwd/pair.h>
1617
#include <__fwd/subrange.h>
1718
#include <__fwd/tuple.h>
@@ -76,6 +77,22 @@ template <size_t _Ip, class _Tp, size_t _Size>
7677
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Tp&& get(const array<_Tp, _Size>&&) _NOEXCEPT;
7778
#endif
7879

80+
#if _LIBCPP_STD_VER >= 26
81+
82+
template <size_t _Ip, class _Tp>
83+
_LIBCPP_HIDE_FROM_ABI constexpr _Tp& get(complex<_Tp>&) noexcept;
84+
85+
template <size_t _Ip, class _Tp>
86+
_LIBCPP_HIDE_FROM_ABI constexpr _Tp&& get(complex<_Tp>&&) noexcept;
87+
88+
template <size_t _Ip, class _Tp>
89+
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp& get(const complex<_Tp>&) noexcept;
90+
91+
template <size_t _Ip, class _Tp>
92+
_LIBCPP_HIDE_FROM_ABI constexpr const _Tp&& get(const complex<_Tp>&&) noexcept;
93+
94+
#endif // _LIBCPP_STD_VER >= 26
95+
7996
#if _LIBCPP_STD_VER >= 20
8097

8198
namespace ranges {

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>
@@ -41,6 +42,13 @@ struct __tuple_like_impl<array<_Tp, _Size> > : true_type {};
4142
template <class _Ip, class _Sp, ranges::subrange_kind _Kp>
4243
struct __tuple_like_impl<ranges::subrange<_Ip, _Sp, _Kp> > : true_type {};
4344

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

libcxx/include/complex

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,31 @@ 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
*/
@@ -331,6 +356,20 @@ public:
331356
*this = *this / complex(__c.real(), __c.imag());
332357
return *this;
333358
}
359+
360+
#if _LIBCPP_STD_VER >= 26
361+
template <size_t _Ip, class _Xp>
362+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
363+
364+
template <size_t _Ip, class _Xp>
365+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
366+
367+
template <size_t _Ip, class _Xp>
368+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
369+
370+
template <size_t _Ip, class _Xp>
371+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
372+
#endif
334373
};
335374

336375
template <>
@@ -408,6 +447,20 @@ public:
408447
*this = *this / complex(__c.real(), __c.imag());
409448
return *this;
410449
}
450+
451+
#if _LIBCPP_STD_VER >= 26
452+
template <size_t _Ip, class _Xp>
453+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
454+
455+
template <size_t _Ip, class _Xp>
456+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
457+
458+
template <size_t _Ip, class _Xp>
459+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
460+
461+
template <size_t _Ip, class _Xp>
462+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
463+
#endif
411464
};
412465

413466
template <>
@@ -480,6 +533,20 @@ public:
480533
*this = *this / complex(__c.real(), __c.imag());
481534
return *this;
482535
}
536+
537+
#if _LIBCPP_STD_VER >= 26
538+
template <size_t _Ip, class _Xp>
539+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
540+
541+
template <size_t _Ip, class _Xp>
542+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
543+
544+
template <size_t _Ip, class _Xp>
545+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
546+
547+
template <size_t _Ip, class _Xp>
548+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
549+
#endif
483550
};
484551

485552
template <>
@@ -553,6 +620,20 @@ public:
553620
*this = *this / complex(__c.real(), __c.imag());
554621
return *this;
555622
}
623+
624+
#if _LIBCPP_STD_VER >= 26
625+
template <size_t _Ip, class _Xp>
626+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>&) noexcept;
627+
628+
template <size_t _Ip, class _Xp>
629+
friend _LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&&) noexcept;
630+
631+
template <size_t _Ip, class _Xp>
632+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>&) noexcept;
633+
634+
template <size_t _Ip, class _Xp>
635+
friend _LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&&) noexcept;
636+
#endif
556637
};
557638

558639
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) {
13521433
}
13531434
#endif // !_LIBCPP_HAS_NO_LOCALIZATION
13541435

1436+
#if _LIBCPP_STD_VER >= 26
1437+
1438+
// [complex.tuple], tuple interface
1439+
1440+
template <class _Tp>
1441+
struct tuple_size;
1442+
1443+
template <class _Tp>
1444+
struct tuple_size<complex<_Tp>> : integral_constant<size_t, 2> {};
1445+
1446+
template <size_t _Ip, class _Tp>
1447+
struct tuple_element;
1448+
1449+
template <size_t _Ip, class _Tp>
1450+
struct tuple_element<_Ip, complex<_Tp>> {
1451+
static_assert(_Ip < 2, "Index value is out of range.");
1452+
using type = _Tp;
1453+
};
1454+
1455+
template <size_t _Ip, class _Xp>
1456+
_LIBCPP_HIDE_FROM_ABI constexpr _Xp& get(complex<_Xp>& __z) noexcept {
1457+
static_assert(_Ip < 2, "Index value is out of range.");
1458+
if constexpr (_Ip == 0) {
1459+
return static_cast<_Xp&>(__z.__re_);
1460+
} else {
1461+
return static_cast<_Xp&>(__z.__im_);
1462+
}
1463+
}
1464+
1465+
template <size_t _Ip, class _Xp>
1466+
_LIBCPP_HIDE_FROM_ABI constexpr _Xp&& get(complex<_Xp>&& __z) noexcept {
1467+
static_assert(_Ip < 2, "Index value is out of range.");
1468+
if constexpr (_Ip == 0) {
1469+
return static_cast<_Xp&&>(__z.__re_);
1470+
} else {
1471+
return static_cast<_Xp&&>(__z.__im_);
1472+
}
1473+
}
1474+
1475+
template <size_t _Ip, class _Xp>
1476+
_LIBCPP_HIDE_FROM_ABI constexpr const _Xp& get(const complex<_Xp>& __z) noexcept {
1477+
static_assert(_Ip < 2, "Index value is out of range.");
1478+
if constexpr (_Ip == 0) {
1479+
return static_cast<const _Xp&>(__z.__re_);
1480+
} else {
1481+
return static_cast<const _Xp&>(__z.__im_);
1482+
}
1483+
}
1484+
1485+
template <size_t _Ip, class _Xp>
1486+
_LIBCPP_HIDE_FROM_ABI constexpr const _Xp&& get(const complex<_Xp>&& __z) noexcept {
1487+
static_assert(_Ip < 2, "Index value is out of range.");
1488+
if constexpr (_Ip == 0) {
1489+
return static_cast<const _Xp&&>(__z.__re_);
1490+
} else {
1491+
return static_cast<const _Xp&&>(__z.__im_);
1492+
}
1493+
}
1494+
1495+
#endif // _LIBCPP_STD_VER >= 26
1496+
13551497
#if _LIBCPP_STD_VER >= 14
13561498
// Literal suffix for complex number literals [complex.literals]
13571499
inline namespace literals {

libcxx/include/libcxx.imp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@
421421
{ include: [ "<__fwd/array.h>", "private", "<array>", "public" ] },
422422
{ include: [ "<__fwd/bit_reference.h>", "private", "<bitset>", "public" ] },
423423
{ include: [ "<__fwd/bit_reference.h>", "private", "<vector>", "public" ] },
424+
{ include: [ "<__fwd/complex.h>", "private", "<complex>", "public" ] },
424425
{ include: [ "<__fwd/fstream.h>", "private", "<fstream>", "public" ] },
425426
{ include: [ "<__fwd/hash.h>", "private", "<functional>", "public" ] },
426427
{ 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
@@ -1197,6 +1197,8 @@ module std_private_compare_synth_three_way [system] { header "__c
11971197
module std_private_compare_three_way_comparable [system] { header "__compare/three_way_comparable.h" }
11981198
module std_private_compare_weak_order [system] { header "__compare/weak_order.h" }
11991199

1200+
module std_private_complex_complex_fwd [system] { header "__fwd/complex.h" }
1201+
12001202
module std_private_concepts_arithmetic [system] { header "__concepts/arithmetic.h" }
12011203
module std_private_concepts_assignable [system] { header "__concepts/assignable.h" }
12021204
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 {
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
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+
// UNSUPPORTED: c++03, c++11, c++14, c++17
10+
11+
// <tuple>
12+
13+
#include <array>
14+
#include <complex>
15+
#include <ranges>
16+
#include <tuple>
17+
18+
#include "test_iterators.h"
19+
20+
static_assert(!std::__tuple_like<int>);
21+
22+
static_assert(std::__tuple_like<std::array<int, 0>>);
23+
static_assert(std::__tuple_like<std::array<int, 1>>);
24+
static_assert(std::__tuple_like<std::array<int, 2>>);
25+
static_assert(std::__tuple_like<std::array<int, 2728>>);
26+
27+
#if _LIBCPP_STD_VER >= 26
28+
static_assert(std::__tuple_like<std::complex<float>>);
29+
static_assert(std::__tuple_like<std::complex<double>>);
30+
static_assert(std::__tuple_like<std::complex<long double>>);
31+
#endif
32+
33+
static_assert(std::__tuple_like<std::pair<int, float>>);
34+
35+
static_assert(std::__tuple_like<std::tuple<int>>);
36+
static_assert(std::__tuple_like<std::tuple<int, float>>);
37+
static_assert(std::__tuple_like<std::tuple<int, float, double>>);
38+
39+
using FI = forward_iterator<int*>;
40+
static_assert(std::__tuple_like<std::ranges::subrange<FI, FI, std::ranges::subrange_kind::sized>>);
41+
static_assert(std::__tuple_like<std::ranges::subrange<FI, FI, std::ranges::subrange_kind::unsized>>);
42+
static_assert(std::__tuple_like<std::ranges::subrange<int*, int*, std::ranges::subrange_kind::sized>>);
43+
static_assert(std::__tuple_like<std::ranges::subrange<int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>);
44+
45+
template <typename Iter>
46+
void test_subrange_sized() {
47+
static_assert(std::__tuple_like<std::ranges::subrange<Iter, Iter, std::ranges::subrange_kind::sized>>);
48+
}
49+
50+
template <typename Iter>
51+
void test_subrange_unsized() {
52+
static_assert(std::__tuple_like<std::ranges::subrange<Iter, Iter, std::ranges::subrange_kind::unsized>>);
53+
}
54+
55+
void test() {
56+
test_subrange_sized<forward_iterator<int*>>();
57+
test_subrange_sized<bidirectional_iterator<int*>>();
58+
test_subrange_sized<random_access_iterator<int*>>();
59+
test_subrange_sized<contiguous_iterator<int*>>();
60+
test_subrange_sized<int*>();
61+
62+
test_subrange_sized<forward_iterator<int const*>>();
63+
test_subrange_sized<bidirectional_iterator<int const*>>();
64+
test_subrange_sized<random_access_iterator<int const*>>();
65+
test_subrange_sized<contiguous_iterator<int const*>>();
66+
test_subrange_sized<int const*>();
67+
68+
test_subrange_unsized<forward_iterator<int*>>();
69+
test_subrange_unsized<bidirectional_iterator<int*>>();
70+
static_assert(std::__tuple_like<std::ranges::subrange<int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>);
71+
72+
test_subrange_unsized<forward_iterator<int const*>>();
73+
test_subrange_unsized<bidirectional_iterator<int const*>>();
74+
static_assert(
75+
std::__tuple_like<std::ranges::subrange<const int*, std::nullptr_t, std::ranges::subrange_kind::unsized>>);
76+
}

0 commit comments

Comments
 (0)