This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
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-07-27
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_simd
synopsis, 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 insideexplicit
evaluates tofalse
if and only if the floating-point conversion rank ofT::value_type
is 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-type
where therebind_t<typename T::value_type, basic_simd>i
th element is initialized to the result ofcmplx-func(operator[](i))
for alli
in the range[0, size())
, wherecmplx-func
is 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
explicit
evaluates tofalse
if and only if the floating-point conversion rank ofT::value_type
is 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 this CD preview draft.
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>constexprexplicit(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-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>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 insideexplicit
evaluates tofalse
if and only if the floating-point conversion rank ofT::value_type
is 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-type
where therebind_t<typename T::value_type, basic_vec>i
th element is initialized to the result ofcmplx-func(operator[](i))
for alli
in the range[0, size())
, wherecmplx-func
is 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
.[…]