This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.
Section: 29.10.9.1 [simd.mask.overview] Status: NAD Submitter: Arthur O'Dwyer Opened: 2025-10-02 Last modified: 2026-05-22
Priority: 3
View all issues with NAD 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.
[2026-05-22 LWG telecon. Status changed: New → NAD.]
Due to Core rules about overload resolution for a braced-init-list,
making the constructor explicit would not change the ambiguity.
Even if it did, the implementation could add other unspecified constructors
that would still make the call ambiguous. LWG does not feel that the example
is something that we would feel needs to be supported. If you want to call
that overloaded function, use a named type not a braced-init-list.
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 {}; }
[…]
};
}