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.
Section: 29.10.9.1 [simd.mask.overview] Status: New Submitter: Arthur O'Dwyer Opened: 2025-10-02 Last modified: 2025-10-22
Priority: 3
View all issues with New status.
Discussion:
29.10.9.1 [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.
[2025-10-22; Reflector poll.]
Set priority to 3 after reflector poll.
simd-iterator can only be constructed only by basic_vec,
and basic_mask objects.
This is NAD as user cannot rely on standard types not being constructible per
16.4.6.5 [member.functions] p2. The example would not be fixed by adding
the explicit in a conforming implementation, and changes in return
specification are editorial.
Proposed resolution:
This wording is relative to N5014.
Modify 29.10.6 [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 29.10.7.1 [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 29.10.9.1 [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 {}; }
[…]
};
}