diff --git a/stl/inc/spanstream b/stl/inc/spanstream index 77a3bc478d9..bf189b063a5 100644 --- a/stl/inc/spanstream +++ b/stl/inc/spanstream @@ -190,6 +190,11 @@ void swap(basic_spanbuf<_Elem, _Traits>& _Left, basic_spanbuf<_Elem, _Traits>& _ _Left.swap(_Right); } +template +span<_Elem, _Extent> _As_nonconst_span(const span _Span) noexcept { + return span<_Elem, _Extent>{const_cast<_Elem*>(_Span.data()), _Span.size()}; +} + _EXPORT_STD template class basic_ispanstream : public basic_istream<_Elem, _Traits> { private: @@ -207,9 +212,6 @@ public: explicit basic_ispanstream(_STD span<_Elem> _Span, ios_base::openmode _Which = ios_base::in) : _Mybase(_STD addressof(_Buf)), _Buf(_Span, _Which | ios_base::in) {} - explicit basic_ispanstream(_STD span _Span) - : basic_ispanstream(_STD span<_Elem>{const_cast<_Elem*>(_Span.data()), _Span.size()}) {} - basic_ispanstream(const basic_ispanstream&) = delete; basic_ispanstream(basic_ispanstream&& _Right) : _Mybase(_STD move(_Right)), _Buf(_STD move(_Right._Buf)) { @@ -220,7 +222,8 @@ public: requires ( !convertible_to<_ReadOnlyRange, _STD span<_Elem>> && convertible_to<_ReadOnlyRange, _STD span>) explicit basic_ispanstream(_ReadOnlyRange&& _Range) - : basic_ispanstream(static_cast<_STD span>(_STD forward<_ReadOnlyRange>(_Range))) {} + : basic_ispanstream( + _STD _As_nonconst_span(static_cast<_STD span>(_STD forward<_ReadOnlyRange>(_Range)))) {} basic_ispanstream& operator=(const basic_ispanstream&) = delete; @@ -254,7 +257,7 @@ public: !convertible_to<_ReadOnlyRange, _STD span<_Elem>> && convertible_to<_ReadOnlyRange, _STD span>) void span(_ReadOnlyRange&& _Range) noexcept { const auto _Sp = static_cast<_STD span>(_STD forward<_ReadOnlyRange>(_Range)); - this->span(_STD span<_Elem>{const_cast<_Elem*>(_Sp.data()), _Sp.size()}); + rdbuf()->span(_STD _As_nonconst_span(_Sp)); } private: diff --git a/tests/std/tests/P0448R4_spanstream/test.cpp b/tests/std/tests/P0448R4_spanstream/test.cpp index 77f69db28d8..64e91731b63 100644 --- a/tests/std/tests/P0448R4_spanstream/test.cpp +++ b/tests/std/tests/P0448R4_spanstream/test.cpp @@ -674,6 +674,28 @@ void test_ispanstream() { assert(static_cast(special_range_constructed.rdbuf())->epptr() == nullptr); } + { // GH-5308: : Constructing ispanstream from string no longer compiles since VS 17.13 + basic_string str(42, static_cast('*')); + basic_ispanstream from_string_constructed{str}; + assert(from_string_constructed.span().data() == str.data()); + assert(static_cast(from_string_constructed.rdbuf())->eback() == str.data()); + assert(static_cast(from_string_constructed.rdbuf())->gptr() == str.data()); + assert(static_cast(from_string_constructed.rdbuf())->egptr() == str.data() + str.size()); + assert(static_cast(from_string_constructed.rdbuf())->pbase() == nullptr); + assert(static_cast(from_string_constructed.rdbuf())->pptr() == nullptr); + assert(static_cast(from_string_constructed.rdbuf())->epptr() == nullptr); + + basic_ispanstream from_string_reset{span{}}; + from_string_reset.span(str); + assert(from_string_reset.span().data() == str.data()); + assert(static_cast(from_string_reset.rdbuf())->eback() == str.data()); + assert(static_cast(from_string_reset.rdbuf())->gptr() == str.data()); + assert(static_cast(from_string_reset.rdbuf())->egptr() == str.data() + str.size()); + assert(static_cast(from_string_reset.rdbuf())->pbase() == nullptr); + assert(static_cast(from_string_reset.rdbuf())->pptr() == nullptr); + assert(static_cast(from_string_reset.rdbuf())->epptr() == nullptr); + } + { // span CharT buffer[10]; basic_ispanstream is{span{buffer}};