Title
Ambiguities of `simd::basic_vec` constructor
Status
new
Section
[simd.ctor]
Submitter
Hewill Kang

Created on 2025-09-29.00:00:00 last changed 1 week ago

Messages

Date: 2025-10-03.14:09:00

Proposed resolution:

This wording is relative to N5014.

  1. Modify [simd.ctor] as indicated:

    template<class G> constexpr explicit basic_vec(G&& gen);
    

    -8- Let Fromi denote the type decltype(gen(integral_constant<simd-size-type, i>())).

    -9- Constraints:

    1. (9.?) — constructible_from<value_type, G> is false.

    2. (9.?) — Fromi satisfies convertible_to<value_type> for all i in the range of [0, size()). In addition, for all i in the range of [0, size()), if Fromi is an arithmetic type, conversion from Fromi to value_type is value-preserving.

    […]
    template<class R, class... Flags>
      constexpr basic_vec(R&& r, flags<Flags...> = {});
    template<class R, class... Flags>
      constexpr basic_vec(R&& r, const mask_type& mask, flags<Flags...> = {});
    

    -12- Let mask be `mask_type(true)` for the overload with no `mask` parameter.

    -13- Constraints:

    1. (13.1) — `R` models `ranges::contiguous_range` and `ranges::sized_range`,

    2. (13.2) — `ranges::size(r)` is a constant expression, and

    3. (13.3) — `ranges::size(r)` is equal to `size()`.,

    4. (13.?) — constructible_from<value_type, R> is `false`, and

    5. (13.?) — r(integral_constant<simd-size-type, 0>()) is not a valid expression.

Date: 2025-09-29.00:00:00

The broadcasting, generator-based, and range constructors of `simd::basic_vec` all take a single argument, and their constraints are not mutually exclusive.

This means that when a type satisfies both characteristics, such as a range that can be converted to a `value_type`, this will lead to ambiguity:

#include <simd>

struct S {
  operator double() const;       // basic_vec(U&& value)
  
  double operator()(int) const;  // basic_vec(G&& gen)

  double* begin() const;         // basic_vec(R&& r, flags<Flags...> = {});
  double* end() const;
  constexpr static int size() { return 2; }
};

int main() {
  std::simd::vec<double> simd(S{}); // error: call of overloaded 'basic_simd(S)' is ambiguous
}

Do we need more constraints, similar to the one in string_view(R&& r) that requires `R` not to be convertible to `const char*`, to make the above work, i.e., only invoke the broadcasting constructor?

History
Date User Action Args
2025-10-03 14:09:00adminsetmessages: + msg15100
2025-09-29 00:00:00admincreate