Skip to content

Commit 25cfafb

Browse files
<spanstream>: Fix ambiguity among constructors of basic_ispanstream (#5309)
1 parent dfdccda commit 25cfafb

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

stl/inc/spanstream

+8-5
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@ void swap(basic_spanbuf<_Elem, _Traits>& _Left, basic_spanbuf<_Elem, _Traits>& _
190190
_Left.swap(_Right);
191191
}
192192

193+
template <class _Elem, size_t _Extent>
194+
span<_Elem, _Extent> _As_nonconst_span(const span<const _Elem, _Extent> _Span) noexcept {
195+
return span<_Elem, _Extent>{const_cast<_Elem*>(_Span.data()), _Span.size()};
196+
}
197+
193198
_EXPORT_STD template <class _Elem, class _Traits>
194199
class basic_ispanstream : public basic_istream<_Elem, _Traits> {
195200
private:
@@ -207,9 +212,6 @@ public:
207212
explicit basic_ispanstream(_STD span<_Elem> _Span, ios_base::openmode _Which = ios_base::in)
208213
: _Mybase(_STD addressof(_Buf)), _Buf(_Span, _Which | ios_base::in) {}
209214

210-
explicit basic_ispanstream(_STD span<const _Elem> _Span)
211-
: basic_ispanstream(_STD span<_Elem>{const_cast<_Elem*>(_Span.data()), _Span.size()}) {}
212-
213215
basic_ispanstream(const basic_ispanstream&) = delete;
214216

215217
basic_ispanstream(basic_ispanstream&& _Right) : _Mybase(_STD move(_Right)), _Buf(_STD move(_Right._Buf)) {
@@ -220,7 +222,8 @@ public:
220222
requires (
221223
!convertible_to<_ReadOnlyRange, _STD span<_Elem>> && convertible_to<_ReadOnlyRange, _STD span<const _Elem>>)
222224
explicit basic_ispanstream(_ReadOnlyRange&& _Range)
223-
: basic_ispanstream(static_cast<_STD span<const _Elem>>(_STD forward<_ReadOnlyRange>(_Range))) {}
225+
: basic_ispanstream(
226+
_STD _As_nonconst_span(static_cast<_STD span<const _Elem>>(_STD forward<_ReadOnlyRange>(_Range)))) {}
224227

225228
basic_ispanstream& operator=(const basic_ispanstream&) = delete;
226229

@@ -254,7 +257,7 @@ public:
254257
!convertible_to<_ReadOnlyRange, _STD span<_Elem>> && convertible_to<_ReadOnlyRange, _STD span<const _Elem>>)
255258
void span(_ReadOnlyRange&& _Range) noexcept {
256259
const auto _Sp = static_cast<_STD span<const _Elem>>(_STD forward<_ReadOnlyRange>(_Range));
257-
this->span(_STD span<_Elem>{const_cast<_Elem*>(_Sp.data()), _Sp.size()});
260+
rdbuf()->span(_STD _As_nonconst_span(_Sp));
258261
}
259262

260263
private:

tests/std/tests/P0448R4_spanstream/test.cpp

+22
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,28 @@ void test_ispanstream() {
674674
assert(static_cast<test_buf*>(special_range_constructed.rdbuf())->epptr() == nullptr);
675675
}
676676

677+
{ // GH-5308: <spanstream>: Constructing ispanstream from string no longer compiles since VS 17.13
678+
basic_string<CharT> str(42, static_cast<CharT>('*'));
679+
basic_ispanstream<CharT> from_string_constructed{str};
680+
assert(from_string_constructed.span().data() == str.data());
681+
assert(static_cast<test_buf*>(from_string_constructed.rdbuf())->eback() == str.data());
682+
assert(static_cast<test_buf*>(from_string_constructed.rdbuf())->gptr() == str.data());
683+
assert(static_cast<test_buf*>(from_string_constructed.rdbuf())->egptr() == str.data() + str.size());
684+
assert(static_cast<test_buf*>(from_string_constructed.rdbuf())->pbase() == nullptr);
685+
assert(static_cast<test_buf*>(from_string_constructed.rdbuf())->pptr() == nullptr);
686+
assert(static_cast<test_buf*>(from_string_constructed.rdbuf())->epptr() == nullptr);
687+
688+
basic_ispanstream<CharT> from_string_reset{span<CharT>{}};
689+
from_string_reset.span(str);
690+
assert(from_string_reset.span().data() == str.data());
691+
assert(static_cast<test_buf*>(from_string_reset.rdbuf())->eback() == str.data());
692+
assert(static_cast<test_buf*>(from_string_reset.rdbuf())->gptr() == str.data());
693+
assert(static_cast<test_buf*>(from_string_reset.rdbuf())->egptr() == str.data() + str.size());
694+
assert(static_cast<test_buf*>(from_string_reset.rdbuf())->pbase() == nullptr);
695+
assert(static_cast<test_buf*>(from_string_reset.rdbuf())->pptr() == nullptr);
696+
assert(static_cast<test_buf*>(from_string_reset.rdbuf())->epptr() == nullptr);
697+
}
698+
677699
{ // span
678700
CharT buffer[10];
679701
basic_ispanstream<CharT> is{span<CharT>{buffer}};

0 commit comments

Comments
 (0)