Created on 2025-10-02.00:00:00 last changed 1 week ago
Proposed resolution:
This wording is relative to N5014.
Modify [simd.iterator] as indicated:
namespace std::simd { template<class V> class simd-iterator { // exposition only V* data_ = nullptr; // exposition only simd-size-type offset_ = 0; // exposition only constexpr explicit simd-iterator(V& d, simd-size-type off) noexcept; // exposition only […] }; }
Modify [simd.overview] as indicated:
namespace std::simd { template<size_t 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>; constexpr iterator begin() noexcept { return iterator({*this, 0}); } constexpr const_iterator begin() const noexcept { return const_iterator({*this, 0}); } constexpr const_iterator cbegin() const noexcept { return const_iterator({*this, 0}); } constexpr default_sentinel_t end() const noexcept { return {}; } constexpr default_sentinel_t cend() const noexcept { return {}; } […] }; }
Modify [simd.mask.overview] as indicated:
namespace std::simd { template<size_t Bytes, class Abi> class basic_mask { public: using value_type = bool; using abi_type = Abi; using iterator = simd-iterator<basic_mask>; using const_iterator = simd-iterator<const basic_mask>; constexpr iterator begin() noexcept { return iterator({*this, 0}); } constexpr const_iterator begin() const noexcept { return const_iterator({*this, 0}); } constexpr const_iterator cbegin() const noexcept { return const_iterator({*this, 0}); } constexpr default_sentinel_t end() const noexcept { return {}; } constexpr default_sentinel_t cend() const noexcept { return {}; } […] }; }
[simd.mask.overview] has
namespace std::simd { template<class V> class simd-iterator { // exposition only V* data_ = nullptr; // exposition only simd-size-type offset_ = 0; // exposition only constexpr simd-iterator(V& d, simd-size-type off) noexcept; // exposition only […] }; […] template<size_t Bytes, class Abi> class basic_mask { public: using value_type = bool; using abi_type = Abi; using iterator = simd-iterator<basic_mask>; using const_iterator = simd-iterator<const basic_mask>; constexpr iterator begin() noexcept { return {*this, 0}; } constexpr const_iterator begin() const noexcept { return {*this, 0}; } constexpr const_iterator cbegin() const noexcept { return {*this, 0}; } constexpr default_sentinel_t end() const noexcept { return {}; } constexpr default_sentinel_t cend() const noexcept { return {}; } […]
It's unclear whether the "exposition-only" constructor is required to be present. If it is present, as written, without `explicit`, then `{someBasicMask, 0}` becomes a valid initializer for an iterator. Evidence in favor of its intentionality: the use of `return {*this, 0}` in `basic_mask::begin()`. (The constructor is `private`, but it still participates in overload resolution and will ambiguate other possible conversions.) But this makes many expressions ambiguous that could be unambiguous to a human.
using Mask = std::simd::mask<int>; void overloaded(std::string, std::pair<Mask, int> kv); void overloaded(std::string, Mask::iterator it); int main() { Mask m; overloaded("the pair is", {m, 0}); // ambiguous? }
At the very least, we should say that this list-initialization is intentional, and add wording to class simd-iterator and/or remove the "exposition only" from simd-iterator's constructor. That makes it clear that the above program is indeed intended to be ambiguous. But IMO we should instead simply make the above program valid.
History | |||
---|---|---|---|
Date | User | Action | Args |
2025-10-04 14:14:10 | admin | set | messages: + msg15122 |
2025-10-02 00:00:00 | admin | create |