mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
[libc++][complex] P2819R2: Add tuple protocol to complex (#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 <zingam@outlook.com>
This commit is contained in:
@@ -40,6 +40,7 @@ Implemented Papers
|
||||
|
||||
- P2637R3 - Member ``visit``
|
||||
- P2652R2 - Disallow User Specialization of ``allocator_traits``
|
||||
- P2819R2 - Add ``tuple`` protocol to ``complex``
|
||||
|
||||
|
||||
Improvements and New Features
|
||||
|
||||
@@ -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|"
|
||||
|
||||
|
@@ -429,6 +429,7 @@ set(files
|
||||
__functional/weak_result_type.h
|
||||
__fwd/array.h
|
||||
__fwd/bit_reference.h
|
||||
__fwd/complex.h
|
||||
__fwd/fstream.h
|
||||
__fwd/hash.h
|
||||
__fwd/ios.h
|
||||
|
||||
42
libcxx/include/__fwd/complex.h
Normal file
42
libcxx/include/__fwd/complex.h
Normal file
@@ -0,0 +1,42 @@
|
||||
//===---------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===---------------------------------------------------------------------===//
|
||||
|
||||
#ifndef _LIBCPP___FWD_COMPLEX_H
|
||||
#define _LIBCPP___FWD_COMPLEX_H
|
||||
|
||||
#include <__config>
|
||||
#include <cstddef>
|
||||
|
||||
#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;
|
||||
|
||||
#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
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <__concepts/derived_from.h>
|
||||
#include <__concepts/equality_comparable.h>
|
||||
#include <__config>
|
||||
#include <__fwd/complex.h>
|
||||
#include <__iterator/concepts.h>
|
||||
#include <__iterator/iterator_traits.h>
|
||||
#include <__ranges/access.h>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include <__config>
|
||||
#include <__fwd/array.h>
|
||||
#include <__fwd/complex.h>
|
||||
#include <__fwd/pair.h>
|
||||
#include <__fwd/subrange.h>
|
||||
#include <__fwd/tuple.h>
|
||||
@@ -40,6 +41,13 @@ struct __tuple_like_impl<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;
|
||||
|
||||
|
||||
@@ -227,12 +227,41 @@ 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
|
||||
|
||||
*/
|
||||
|
||||
#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>
|
||||
|
||||
@@ -244,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>
|
||||
@@ -331,6 +363,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 +454,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 +540,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 +627,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 +1440,67 @@ operator<<(basic_ostream<_CharT, _Traits>& __os, const complex<_Tp>& __x) {
|
||||
}
|
||||
#endif // !_LIBCPP_HAS_NO_LOCALIZATION
|
||||
|
||||
#if _LIBCPP_STD_VER >= 26
|
||||
|
||||
// [complex.tuple], tuple interface
|
||||
|
||||
template <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 __z.__re_;
|
||||
} else {
|
||||
return __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 std::move(__z.__re_);
|
||||
} else {
|
||||
return std::move(__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 __z.__re_;
|
||||
} else {
|
||||
return __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 std::move(__z.__re_);
|
||||
} else {
|
||||
return std::move(__z.__im_);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // _LIBCPP_STD_VER >= 26
|
||||
|
||||
#if _LIBCPP_STD_VER >= 14
|
||||
// Literal suffix for complex number literals [complex.literals]
|
||||
inline namespace literals {
|
||||
@@ -1383,6 +1532,8 @@ _LIBCPP_HIDE_FROM_ABI inline constexpr complex<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>
|
||||
|
||||
@@ -424,6 +424,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" ] },
|
||||
|
||||
@@ -1195,6 +1195,8 @@ module std_private_compare_synth_three_way [system] { header "__c
|
||||
module std_private_compare_three_way_comparable [system] { header "__compare/three_way_comparable.h" }
|
||||
module std_private_compare_weak_order [system] { header "__compare/weak_order.h" }
|
||||
|
||||
module std_private_complex_complex_fwd [system] { header "__fwd/complex.h" }
|
||||
|
||||
module std_private_concepts_arithmetic [system] { header "__concepts/arithmetic.h" }
|
||||
module std_private_concepts_assignable [system] { header "__concepts/assignable.h" }
|
||||
module std_private_concepts_boolean_testable [system] { header "__concepts/boolean_testable.h" }
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -159,6 +159,7 @@ compare limits
|
||||
compare type_traits
|
||||
compare version
|
||||
complex cmath
|
||||
complex cstddef
|
||||
complex iosfwd
|
||||
complex sstream
|
||||
complex stdexcept
|
||||
|
||||
|
@@ -160,6 +160,7 @@ compare limits
|
||||
compare type_traits
|
||||
compare version
|
||||
complex cmath
|
||||
complex cstddef
|
||||
complex iosfwd
|
||||
complex sstream
|
||||
complex stdexcept
|
||||
|
||||
|
@@ -160,6 +160,7 @@ compare limits
|
||||
compare type_traits
|
||||
compare version
|
||||
complex cmath
|
||||
complex cstddef
|
||||
complex iosfwd
|
||||
complex sstream
|
||||
complex stdexcept
|
||||
|
||||
|
@@ -160,6 +160,7 @@ compare limits
|
||||
compare type_traits
|
||||
compare version
|
||||
complex cmath
|
||||
complex cstddef
|
||||
complex iosfwd
|
||||
complex sstream
|
||||
complex stdexcept
|
||||
|
||||
|
@@ -166,6 +166,7 @@ compare limits
|
||||
compare type_traits
|
||||
compare version
|
||||
complex cmath
|
||||
complex cstddef
|
||||
complex iosfwd
|
||||
complex sstream
|
||||
complex stdexcept
|
||||
|
||||
|
@@ -111,6 +111,7 @@ compare cstdint
|
||||
compare limits
|
||||
compare version
|
||||
complex cmath
|
||||
complex cstddef
|
||||
complex sstream
|
||||
complex version
|
||||
concepts cstddef
|
||||
|
||||
|
@@ -111,6 +111,7 @@ compare cstdint
|
||||
compare limits
|
||||
compare version
|
||||
complex cmath
|
||||
complex cstddef
|
||||
complex sstream
|
||||
complex version
|
||||
concepts cstddef
|
||||
|
||||
|
@@ -0,0 +1,93 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17
|
||||
|
||||
// <tuple>
|
||||
|
||||
// 22.4.3 Concept `tuple-like` [tuple.like]
|
||||
//
|
||||
// template<class T>
|
||||
// concept tuple-like; // exposition only
|
||||
|
||||
#include <array>
|
||||
#include <complex>
|
||||
#include <ranges>
|
||||
#include <tuple>
|
||||
|
||||
#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>>);
|
||||
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>>);
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20, c++23
|
||||
|
||||
// <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 <concepts>
|
||||
#include <ranges>
|
||||
#include <vector>
|
||||
#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::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 &
|
||||
{
|
||||
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});
|
||||
}
|
||||
{
|
||||
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});
|
||||
}
|
||||
// `get()` allows using `complex` with structured bindings
|
||||
{
|
||||
std::complex<T> c{T{27}, T{28}};
|
||||
|
||||
auto [r, i]{c};
|
||||
static_assert(std::same_as<T, decltype(r)>);
|
||||
assert(r == T{27});
|
||||
static_assert(std::same_as<T, decltype(i)>);
|
||||
assert(i == T{28});
|
||||
}
|
||||
{
|
||||
std::complex<T> c{T{27}, T{28}};
|
||||
|
||||
auto& [r, i]{c};
|
||||
static_assert(std::same_as<T, decltype(r)>);
|
||||
assert(r == T{27});
|
||||
static_assert(std::same_as<T, decltype(i)>);
|
||||
assert(i == T{28});
|
||||
}
|
||||
// `get()` allows using `complex` with ranges
|
||||
{
|
||||
std::complex<T> arr[]{{T{27}, T{28}}, {T{82}, T{94}}};
|
||||
|
||||
std::same_as<std::vector<T>> decltype(auto) reals{
|
||||
arr | std::views::elements<0> | std::ranges::to<std::vector<T>>()};
|
||||
assert(reals.size() == 2);
|
||||
assert(reals[0] == T{27});
|
||||
assert(reals[1] == T{82});
|
||||
|
||||
std::same_as<std::vector<T>> decltype(auto) imags{
|
||||
arr | std::views::elements<1> | std::ranges::to<std::vector<T>>()};
|
||||
assert(reals.size() == 2);
|
||||
assert(imags[0] == T{28});
|
||||
assert(imags[1] == T{94});
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool test() {
|
||||
test<float>();
|
||||
test<double>();
|
||||
test<long double>();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int main(int, char**) {
|
||||
test();
|
||||
static_assert(test());
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -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>();
|
||||
}
|
||||
@@ -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 <complex>
|
||||
#include <concepts>
|
||||
|
||||
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>();
|
||||
}
|
||||
@@ -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 <complex>
|
||||
#include <concepts>
|
||||
|
||||
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>();
|
||||
}
|
||||
@@ -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 <complex>
|
||||
#include <concepts>
|
||||
|
||||
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>();
|
||||
}
|
||||
@@ -1228,7 +1228,7 @@ feature_test_macros = [
|
||||
"name": "__cpp_lib_tuple_like",
|
||||
"values": {
|
||||
"c++23": 202207, # P2165R4 Compatibility between tuple, pair and tuple-like objects
|
||||
"c++26": 202311, # P2819R2 Add tuple protocol to complex
|
||||
"c++26": 202311, # P2819R2 Add tuple protocol to complex (implemented)
|
||||
},
|
||||
"headers": ["map", "tuple", "unordered_map", "utility"],
|
||||
"unimplemented": True,
|
||||
|
||||
Reference in New Issue
Block a user