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.
std::span<volatile T, E>
is made ill-formed by P2278R4 when T
is a normal class typeSection: 23.7.2.2.1 [span.overview] Status: New Submitter: Jiang An Opened: 2022-11-06 Last modified: 2025-03-22
Priority: 2
View all other issues in [span.overview].
View all issues with New status.
Discussion:
This issue is discovered when implementing the
span
part of P2278R4 in MSVC STL.
const_iterator
member type to std::span
, which required its
iterator
type to model std::input_iterator
(same for const_reverse_iterator
and
reverse_iterator
).
However, when element_type
is volatile T
and T
is a class type, the iterator
type generally fails to satisfy input_iterator
, because:
input_iterator<iterator>
requires indirectly_readable<iterator>
;
indirectly_readable<iterator>
requires common_reference_with<iterator_reference_t<iterator>&&,
iterator_rvalue_reference_t<iterator>&&>
, that is
common_reference_with<volatile T&, volatile T&&>
;
common_reference_t<volatile T&, volatile T&&>
is T
(which is problematic),
and thus common_reference_with<volatile T&, volatile T&&>
requires both
convertible_to<volatile T&, T>
and convertible_to<volatile T&&, T>
;
However, the class type T
generally doesn't have constructors from volatile T
or
const volatile T
glvalues, and thus neither convertible_to<volatile T&, T>
and
convertible_to<volatile T&&, T>
is satisfied.
Ideally, span
should not require any form of construction of element_type
. Although usages of
class types provided by the standard library via volatile
glvalues are generally not supported, I think
span<volatile T, E>
is still useful for some user-defined class type T
, and thus shouldn't be forbidden.
[Kona 2022-11-12; Set priority to 2]
[2025-03-22; Jiang An comments and provides wording]
The proposed resolution relaxes the input_iterator
concept (which in turn relaxes stronger iterator concepts)
and extends iter_const_reference_t
and the exposition only iter-const-rvalue-reference-t
aliases. Another approach can be just relaxing the indirectly_readable
concept, but its impact may be larger
than expected.
Proposed resolution:
This wording is relative to N5008.
Modify 24.2 [iterator.synopsis], header <iterator>
synopsis, as indicated:
[…] // 24.3.4.9 [iterator.concept.input], concept input_iterator template<class I> concept deref-to-value-t = see below; // freestanding template<class I> concept weakly-indirectly-readable = see below; // freestanding template<class I> concept input_iterator = see below; // freestanding […] // 24.5.3.2 [const.iterators.alias], alias templates template<indirectly_readableweakly-indirectly-readable I> using iter_const_reference_t = see below;
Modify 24.3.4.9 [iterator.concept.input], concept input_iterator
synopsis, as indicated:
template<class I> concept deref-to-value-t-impl = // exposition only same_as<remove_cvref_t<iter_reference_t<I>>, iter_value_t<I>> && is_object_v<iter_value_t<I>>; template<class I> concept deref-to-value-t = // exposition only deref-to-value-t-impl<remove_cvref_t<I>>; template<class I> concept weakly-indirectly-readable = // exposition only deref-to-value-t<I> || indirectly_readable<I>; template<class I> concept input_iterator = input_or_output_iterator<I> &&indirectly_readableweakly-indirectly-readable<I> && requires { typename ITER_CONCEPT(I); } && derived_from<ITER_CONCEPT(I), input_iterator_tag>;
Modify 24.5.3.2 [const.iterators.alias] as indicated:
template<class T> using ref-add-const-t = see below;-?- Result: If
is_lvalue_reference_v<T>
istrue
,const remove_reference_t<T>&
. Otherwise, ifis_rvalue_reference_v<T>
istrue
,const remove_reference_t<T>&&
. Otherwise,T
.template<indirectly_readableweakly-indirectly-readable It> using iter_const_reference_t = see below;common_reference_t<const iter_value_t<It>&&, iter_reference_t<It>>;-?- Result: If
It
modelsderef-to-value-t
,ref-add-const-t<iter_reference_t<It>>
. Otherwise,common_reference_t<const iter_value_t<It>&&, iter_reference_t<It>>
.
[Drafting note: The simple
deref-to-value-t
case should be detected first, which avoids unnecessary instantiations and IFNDR-ness.]
Modify 24.5.3.3 [const.iterators.iterator] as indicated:
[…] template<indirectly_readableweakly-indirectly-readable I> using iter-const-rvalue-reference-t = // exposition only common_reference_t<const iter_value_t<I>&&, iter_rvalue_reference_t<I>>; […]