simd<complex>::real/imag is overconstrainedSection: 29.10.8.4 [simd.complex.access] Status: New Submitter: Matthias Kretz Opened: 2025-03-18 Last modified: 2025-08-16
Priority: 2
View all issues with New status.
Discussion:
29.10.8.4 [simd.complex.access] overconstrains the arguments to real and imag.
complex<T>::real/imag allows conversions to T whereas simd<complex<T>>
requires basically an exact match (same_as<simd<T>> modulo ABI tag differences).
complex<double> c = {};
c.real(1.f); // OK
simd<complex<double>> sc = {};
sc.real(simd<float>(1.f)); // ill-formed, should be allowed
The design intent was to match the std::complex<T> interface. In which case
the current wording doesn't match that intent. complex doesn't say real(same_as<T> auto)
but 'real(T)', which allows conversions.
basic_simd(real, imag) constructor. It deduces the type for the
real/imag arguments instead of using a dependent type derived from value_type and ABI tag.
// OK:
complex<double> c{1., 1.f};
// Ill-formed, should be allowed:
simd<complex<double>> sc0(1., 1.);
simd<complex<double>, 4> sc1(simd<double, 4>(1.), simd<float, 4>(1.f));
[2025-06-13; Reflector poll]
Set priority to 2 after reflector poll.
Previous resolution [SUPERSEDED]:
This wording is relative to N5008.
Modify 29.10.7.1 [simd.overview], class template
basic_simdsynopsis, as indicated:namespace std::datapar { template<class T, class Abi> class basic_simd { public: using value_type = T; using mask_type = basic_simd_mask<sizeof(T), Abi>; using abi_type = Abi; using real-type = rebind_t<typename T::value_type, basic_simd> // exposition-only // 29.10.7.2 [simd.ctor], basic_simd constructors […]template<simd-floating-point V>constexpr explicit(see below) basic_simd(const real-typeV& reals, const real-typeV& imags = {}) noexcept; […] // 29.10.8.4 [simd.complex.access], basic_simd complex-value accessors constexpr real-typeautoreal() const noexcept; constexpr real-typeautoimag() const noexcept;template<simd-floating-point V>constexpr void real(const real-typeV& v) noexcept;template<simd-floating-point V>constexpr void imag(const real-typeV& v) noexcept; […] }; […] }Modify 29.10.7.2 [simd.ctor] as indicated:
template<simd-floating-point V>constexpr explicit(see below) basic_simd(const real-typeV& reals, const real-typeV& imags = {}) noexcept;-19- Constraints:
(19.1) —simd-complex<basic_simd>is modeled., and
(19.2) —V::size() == size()istrue.[…]
-21- Remarks: The expression insideexplicitevaluates tofalseif and only if the floating-point conversion rank ofT::value_typeis greater than or equal to the floating-point conversion rank ofreal-type.V::value_typeModify 29.10.8.4 [simd.complex.access] as indicated:
constexpr real-typeautoreal() const noexcept; constexpr real-typeautoimag() const noexcept;-1- Constraints:
-2- Returns: An object of typesimd-complex<basic_simd>is modeled.real-typewhere therebind_t<typename T::value_type, basic_simd>ith element is initialized to the result ofcmplx-func(operator[](i))for alliin the range[0, size()), wherecmplx-funcis the corresponding function from<complex>.template<simd-floating-point V>constexpr void real(const real-typeV& v) noexcept;template<simd-floating-point V>constexpr void imag(const real-typeV& v) noexcept;-3- Constraints:
(3.1) —simd-complex<basic_simd>is modeled.,
(3.2) —same_as<typename V::value_type, typename T::value_type>is modeled, and
(3.3) —V::size() == size()istrue.[…]
[2025-07-21; Matthias Kretz comments]
The currently shown P/R says:
Remarks: The expression inside
explicitevaluates tofalseif and only if the floating-point conversion rank ofT::value_typeis greater than or equal to the floating-point conversion rank ofreal-type::value_type.
But, by construction, real-type::value_type is the same as T::value_type.
So we get an elaborately worded explicit(false) here (which is correct).
Consequently, the proposed resolution needs to strike explicit(<i>see below</i>)
from 29.10.7.1 [simd.overview] and 29.10.7.2 [simd.ctor] and drop the Remarks paragraph (21).
Proposed resolution:
This wording is relative to N5014.
Modify 29.10.7.1 [simd.overview], class template basic_vec synopsis, as indicated:
namespace std::simd {
template<class T, class Abi> class basic_vec {
public:
using value_type = T;
using mask_type = basic_mask<sizeof(T), Abi>;
using abi_type = Abi;
using iterator = simd-iterator<basic_vec>;
using const_iterator = simd-iterator<const basic_vec>;
using real-type = rebind_t<typename T::value_type, basic_vec> // exposition-only
// 29.10.7.2 [simd.ctor], basic_vec constructors
[…]
template<simd-floating-point V>
constexpr explicit(see below) basic_vec(const real-typeV& reals, const real-typeV& imags = {}) noexcept;
[…]
// 29.10.8.4 [simd.complex.access], basic_vec complex-value accessors
constexpr real-typeauto real() const noexcept;
constexpr real-typeauto imag() const noexcept;
template<simd-floating-point V>
constexpr void real(const real-typeV& v) noexcept;
template<simd-floating-point V>
constexpr void imag(const real-typeV& v) noexcept;
[…]
};
[…]
}
Modify 29.10.7.2 [simd.ctor] as indicated:
template<simd-floating-point V>constexprexplicit(see below)basic_vec(const real-typeV& reals, const real-typeV& imags = {}) noexcept;-19- Constraints:
(19.1) —simd-complex<basic_vec>is modeled., and
(19.2) —V::size() == size()istrue.[…]
-21- Remarks: The expression insideexplicitevaluates tofalseif and only if the floating-point conversion rank ofT::value_typeis greater than or equal to the floating-point conversion rank ofV::value_type.
Modify 29.10.8.4 [simd.complex.access] as indicated:
constexpr real-typeautoreal() const noexcept; constexpr real-typeautoimag() const noexcept;-1- Constraints:
-2- Returns: An object of typesimd-complex<basic_vec>is modeled.real-typewhere therebind_t<typename T::value_type, basic_vec>ith element is initialized to the result ofcmplx-func(operator[](i))for alliin the range[0, size()), wherecmplx-funcis the corresponding function from<complex>.template<simd-floating-point V>constexpr void real(const real-typeV& v) noexcept;template<simd-floating-point V>constexpr void imag(const real-typeV& v) noexcept;-3- Constraints:
(3.1) —simd-complex<basic_vec>is modeled.,
(3.2) —same_as<typename V::value_type, typename T::value_type>is modeled, and
(3.3) —V::size() == size()istrue.[…]