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.7.4 [simd.complex.access] Status: New Submitter: Matthias Kretz Opened: 2025-03-18 Last modified: 2025-03-22
Priority: Not Prioritized
View all issues with New status.
Discussion:
29.10.7.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));
Proposed resolution:
This wording is relative to N5008.
Modify 29.10.6.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.6.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.7.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.6.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_type
Modify 29.10.7.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
.[…]