[libcxx-commits] [libcxx] [libc++] Implement P2819: Add tuple protocol to complex (PR #72776)

A. Jiang via libcxx-commits libcxx-commits at lists.llvm.org
Sun Nov 19 19:14:25 PST 2023


================
@@ -1538,6 +1549,73 @@ inline namespace literals
 } // namespace literals
 #endif
 
+#if _LIBCPP_STD_VER >= 26
+// Tuple interface [complex.tuple]
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS tuple_size<complex<_Tp>>
+  : public integral_constant<size_t, 2> {};
+
+template<size_t _Ip, class _Tp>
+struct _LIBCPP_TEMPLATE_VIS tuple_element<_Ip, complex<_Tp>>
+{
+  static_assert(_Ip < 2, "Index out of bounds in std::tuple_element<std::complex<T>>");
+
+  using type _LIBCPP_NODEBUG = _Tp;
+};
+
+template <size_t _Ip>
+struct __get_complex
+{
+  static_assert(_Ip < 2, "Index out of bounds in std::get<std::complex<T>>");
+
+  template <typename _Tp>
+  struct to_array_type;
+
+  template <typename _Tp>
+  struct to_array_type<complex<_Tp>>
+  {
+    using type _LIBCPP_NODEBUG = _Tp[2];
+  };
+
+  template <class _Tp>
+  static _LIBCPP_HIDE_FROM_ABI constexpr
+  decltype(auto)
+  get(_Tp&& __z) _NOEXCEPT
+  {
+    using _Array_type = typename __get_complex::to_array_type<std::remove_cvref_t<_Tp>>::type;
+    return reinterpret_cast<_ForwardLike<_Tp, _Array_type>>(__z)[_Ip];
----------------
frederick-vs-ja wrote:

Perhapas we can a this member function to `complex` (to the primary template and full specializations):
```C++
#if _LIBCPP_STD_VER >= 26
    template <size_t _Index, class _Self>
    constexpr auto&& __get(this _Self&& __self) noexcept {
        static_assert(_Index < 2, "Invalid index for std::get(complex) overloads.");
        if constexpr (_Indx == 0) {
            return std::forward<_Self>(__self).__re_;
        } else {
            return std::forward<_Self>(__self).__im_;
        }
    }
#endif //  _LIBCPP_STD_VER >= 26
```
(Maybe it's sufficient to accept lvaue references only since we can perform `std::move` in `std::get`.)

And then implement the standard free functions as:
```C++
#if _LIBCPP_STD_VER >= 26
template <size_t _Index, class _Tp>
constexpr _Tp& get(complex<_Tp>& __z) noexcept { return __z.__get<_Index>(); }
// other overloads
#endif //  _LIBCPP_STD_VER >= 26
```

Additionally, I think the overloads set of `std::get` should have the form specified in the standard wording. The difference in the form of the overload set is observable via explicitly specified template arguments.

https://github.com/llvm/llvm-project/pull/72776


More information about the libcxx-commits mailing list