Files
2025-10-25 03:02:53 +03:00

721 lines
30 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[span.streams]
# 31 Input/output library [[input.output]](./#input.output)
## 31.9 Span-based streams [span.streams]
### [31.9.1](#overview) Overview [[span.streams.overview]](span.streams.overview)
[1](#overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10001)
The header <spanstream> defines class templates and types
that associate stream buffers with objects whose types are
specializations of span as described in [[views.span]](views.span "23.7.2.2Class template span")[.](#overview-1.sentence-1)
[*Note [1](#overview-note-1)*:
A user of these classes is responsible for ensuring
that the character sequence represented by the given span outlives the use of the sequence by objects of the classes in [span.streams][.](#overview-1.sentence-2)
Using multiple basic_spanbuf objects
referring to overlapping underlying sequences from different threads,
where at least one basic_spanbuf object is used
for writing to the sequence,
results in a data race[.](#overview-1.sentence-3)
— *end note*]
### [31.9.2](#spanstream.syn) Header <spanstream> synopsis [[spanstream.syn]](spanstream.syn)
[🔗](#lib:spanbuf)
namespace std {// [[spanbuf]](#spanbuf "31.9.3Class template basic_­spanbuf"), class template basic_spanbuftemplate<class charT, class traits = char_traits<charT>>class basic_spanbuf; template<class charT, class traits>void swap(basic_spanbuf<charT, traits>& x, basic_spanbuf<charT, traits>& y); using spanbuf = basic_spanbuf<char>; using wspanbuf = basic_spanbuf<wchar_t>; // [[ispanstream]](#ispanstream "31.9.4Class template basic_­ispanstream"), class template basic_ispanstreamtemplate<class charT, class traits = char_traits<charT>>class basic_ispanstream; template<class charT, class traits>void swap(basic_ispanstream<charT, traits>& x, basic_ispanstream<charT, traits>& y); using ispanstream = basic_ispanstream<char>; using wispanstream = basic_ispanstream<wchar_t>; // [[ospanstream]](#ospanstream "31.9.5Class template basic_­ospanstream"), class template basic_ospanstreamtemplate<class charT, class traits = char_traits<charT>>class basic_ospanstream; template<class charT, class traits>void swap(basic_ospanstream<charT, traits>& x, basic_ospanstream<charT, traits>& y); using ospanstream = basic_ospanstream<char>; using wospanstream = basic_ospanstream<wchar_t>; // [[spanstream]](#spanstream "31.9.6Class template basic_­spanstream"), class template basic_spanstreamtemplate<class charT, class traits = char_traits<charT>>class basic_spanstream; template<class charT, class traits>void swap(basic_spanstream<charT, traits>& x, basic_spanstream<charT, traits>& y); using spanstream = basic_spanstream<char>; using wspanstream = basic_spanstream<wchar_t>;}
### [31.9.3](#spanbuf) Class template basic_spanbuf [[spanbuf]](spanbuf)
#### [31.9.3.1](#spanbuf.general) General [[spanbuf.general]](spanbuf.general)
[🔗](#lib:basic_spanbuf)
namespace std {template<class charT, class traits = char_traits<charT>>class basic_spanbuf : public basic_streambuf<charT, traits> {public:using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [[spanbuf.cons]](#spanbuf.cons "31.9.3.2Constructors"), constructors basic_spanbuf() : basic_spanbuf(ios_base::in | ios_base::out) {}explicit basic_spanbuf(ios_base::openmode which): basic_spanbuf(std::span<charT>(), which) {}explicit basic_spanbuf(std::span<charT> s,
ios_base::openmode which = ios_base::in | ios_base::out);
basic_spanbuf(const basic_spanbuf&) = delete;
basic_spanbuf(basic_spanbuf&& rhs); // [[spanbuf.assign]](#spanbuf.assign "31.9.3.3Assignment and swap"), assignment and swap basic_spanbuf& operator=(const basic_spanbuf&) = delete;
basic_spanbuf& operator=(basic_spanbuf&& rhs); void swap(basic_spanbuf& rhs); // [[spanbuf.members]](#spanbuf.members "31.9.3.4Member functions"), member functions std::span<charT> span() const noexcept; void span(std::span<charT> s) noexcept; protected:// [[spanbuf.virtuals]](#spanbuf.virtuals "31.9.3.5Overridden virtual functions"), overridden virtual functions basic_streambuf<charT, traits>* setbuf(charT*, streamsize) override;
pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which = ios_base::in | ios_base::out) override;
pos_type seekpos(pos_type sp,
ios_base::openmode which = ios_base::in | ios_base::out) override; private: ios_base::openmode *mode*; // *exposition only* std::span<charT> *buf*; // *exposition only*};}
[1](#spanbuf.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10120)
The class template basic_spanbuf is derived from basic_streambuf to associate possibly the input sequence and possibly the output sequence
with a sequence of arbitrary characters[.](#spanbuf.general-1.sentence-1)
The sequence is provided by an object of class span<charT>[.](#spanbuf.general-1.sentence-2)
[2](#spanbuf.general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10126)
For the sake of exposition, the maintained data is presented here as:
- [(2.1)](#spanbuf.general-2.1)
ios_base::openmode *mode*, hasin set if the input sequence can be read, andout set if the output sequence can be written[.](#spanbuf.general-2.1.sentence-1)
- [(2.2)](#spanbuf.general-2.2)
std::span<charT> *buf* is the view to
the underlying character sequence[.](#spanbuf.general-2.2.sentence-1)
#### [31.9.3.2](#spanbuf.cons) Constructors [[spanbuf.cons]](spanbuf.cons)
[🔗](#lib:basic_spanbuf,constructor)
`explicit basic_spanbuf(std::span<charT> s,
ios_base::openmode which = ios_base::in | ios_base::out);
`
[1](#spanbuf.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10147)
*Effects*: Initializes the base class with basic_streambuf() ([[streambuf.cons]](streambuf.cons "31.6.3.2Constructors")),
and *mode* with which[.](#spanbuf.cons-1.sentence-1)
Initializes the internal pointers as if calling span(s)[.](#spanbuf.cons-1.sentence-2)
[🔗](#lib:basic_spanbuf,constructor_)
`basic_spanbuf(basic_spanbuf&& rhs);
`
[2](#spanbuf.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10160)
*Effects*: Initializes the base class with std::move(rhs) and*mode* with std::move(rhs.*mode*) and*buf* with std::move(rhs.*buf*)[.](#spanbuf.cons-2.sentence-1)
The sequence pointers in *this (eback(), gptr(), egptr(),pbase(), pptr(), epptr())
obtain the values which rhs had[.](#spanbuf.cons-2.sentence-2)
It isimplementation-defined
whether rhs.*buf*.empty() returns true after the move[.](#spanbuf.cons-2.sentence-3)
[3](#spanbuf.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10173)
*Postconditions*: Let rhs_p refer to the state of rhs just prior to this construction[.](#spanbuf.cons-3.sentence-1)
- [(3.1)](#spanbuf.cons-3.1)
span().data() == rhs_p.span().data()
- [(3.2)](#spanbuf.cons-3.2)
span().size() == rhs_p.span().size()
- [(3.3)](#spanbuf.cons-3.3)
eback() == rhs_p.eback()
- [(3.4)](#spanbuf.cons-3.4)
gptr() == rhs_p.gptr()
- [(3.5)](#spanbuf.cons-3.5)
egptr() == rhs_p.egptr()
- [(3.6)](#spanbuf.cons-3.6)
pbase() == rhs_p.pbase()
- [(3.7)](#spanbuf.cons-3.7)
pptr() == rhs_p.pptr()
- [(3.8)](#spanbuf.cons-3.8)
epptr() == rhs_p.epptr()
- [(3.9)](#spanbuf.cons-3.9)
getloc() == rhs_p.getloc()
#### [31.9.3.3](#spanbuf.assign) Assignment and swap [[spanbuf.assign]](spanbuf.assign)
[🔗](#lib:operator=,basic_spanbuf)
`basic_spanbuf& operator=(basic_spanbuf&& rhs);
`
[1](#spanbuf.assign-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10198)
*Effects*: Equivalent to:basic_spanbuf tmp{std::move(rhs)};this->swap(tmp);return *this;
[🔗](#lib:swap,basic_spanbuf)
`void swap(basic_spanbuf& rhs);
`
[2](#spanbuf.assign-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10214)
*Effects*: Equivalent to:basic_streambuf<charT, traits>::swap(rhs);
std::swap(*mode*, rhs.*mode*);
std::swap(*buf*, rhs.*buf*);
[🔗](#lib:swap,basic_spanbuf_)
`template<class charT, class traits>
void swap(basic_spanbuf<charT, traits>& x, basic_spanbuf<charT, traits>& y);
`
[3](#spanbuf.assign-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10231)
*Effects*: Equivalent to x.swap(y)[.](#spanbuf.assign-3.sentence-1)
#### [31.9.3.4](#spanbuf.members) Member functions [[spanbuf.members]](spanbuf.members)
[🔗](#lib:span,basic_spanbuf)
`std::span<charT> span() const noexcept;
`
[1](#spanbuf.members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10244)
*Returns*: If ios_base::out is set in *mode*,
returns std::span<charT>(pbase(), pptr()),
otherwise returns *buf*[.](#spanbuf.members-1.sentence-1)
[*Note [1](#spanbuf.members-note-1)*:
In contrast to basic_stringbuf,
the underlying sequence never grows and is not owned[.](#spanbuf.members-1.sentence-2)
An owning copy can be obtained
by converting the result to basic_string<charT>[.](#spanbuf.members-1.sentence-3)
— *end note*]
[🔗](#lib:span,basic_spanbuf_)
`void span(std::span<charT> s) noexcept;
`
[2](#spanbuf.members-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10264)
*Effects*: *buf* = s[.](#spanbuf.members-2.sentence-1)
Initializes the input and output sequences according to *mode*[.](#spanbuf.members-2.sentence-2)
[3](#spanbuf.members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10269)
*Postconditions*:
- [(3.1)](#spanbuf.members-3.1)
If ios_base::out is set in *mode*,pbase() == s.data() && epptr() == pbase() + s.size() is true;
* [(3.1.1)](#spanbuf.members-3.1.1)
in addition, if ios_base::ate is set in *mode*,pptr() == pbase() + s.size() is true,
* [(3.1.2)](#spanbuf.members-3.1.2)
otherwise pptr() == pbase() is true[.](#spanbuf.members-3.1.sentence-1)
- [(3.2)](#spanbuf.members-3.2)
If ios_base::in is set in *mode*,eback() == s.data() && gptr() == eback() && egptr() == eback() + s.size() is true[.](#spanbuf.members-3.2.sentence-1)
#### [31.9.3.5](#spanbuf.virtuals) Overridden virtual functions [[spanbuf.virtuals]](spanbuf.virtuals)
[1](#spanbuf.virtuals-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10292)
[*Note [1](#spanbuf.virtuals-note-1)*:
Because the underlying buffer is of fixed size,
neither overflow, underflow, nor pbackfail can provide useful behavior[.](#spanbuf.virtuals-1.sentence-1)
— *end note*]
[🔗](#lib:seekoff,basic_spanbuf)
`pos_type seekoff(off_type off, ios_base::seekdir way,
ios_base::openmode which = ios_base::in | ios_base::out) override;
`
[2](#spanbuf.virtuals-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10306)
*Effects*: Alters the stream position within one or both of the
controlled sequences, if possible, as follows:
- [(2.1)](#spanbuf.virtuals-2.1)
If ios_base::in is set in which, positions the input sequence;xnext is gptr(), xbeg is eback()[.](#spanbuf.virtuals-2.1.sentence-1)
- [(2.2)](#spanbuf.virtuals-2.2)
If ios_base::out is set in which, positions the output sequence;xnext is pptr(), xbeg is pbase()[.](#spanbuf.virtuals-2.2.sentence-1)
[3](#spanbuf.virtuals-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10319)
If both ios_base::in and ios_base::out are set in which and way is ios_base::cur,
the positioning operation fails[.](#spanbuf.virtuals-3.sentence-1)
[4](#spanbuf.virtuals-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10324)
For a sequence to be positioned,
if its next pointer xnext (either gptr() or pptr())
is a null pointer and
the new offset newoff as computed below is nonzero,
the positioning operation fails[.](#spanbuf.virtuals-4.sentence-1)
Otherwise, the function determines baseoff as a value of type off_type as follows:
- [(4.1)](#spanbuf.virtuals-4.1)
0 when way is ios_base::beg;
- [(4.2)](#spanbuf.virtuals-4.2)
(pptr() - pbase()) for the output sequence, or(gptr() - eback()) for the input sequence
when way is ios_base::cur;
- [(4.3)](#spanbuf.virtuals-4.3)
when way is ios_base::end :
* [(4.3.1)](#spanbuf.virtuals-4.3.1)
(pptr() - pbase()) if ios_base::out is set in *mode* andios_base::in is not set in *mode*,
* [(4.3.2)](#spanbuf.virtuals-4.3.2)
*buf*.size() otherwise[.](#spanbuf.virtuals-4.sentence-2)
[5](#spanbuf.virtuals-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10351)
If baseoff+off would overflow, or
if baseoff+off is less than zero, or
if baseoff+off is greater than *buf*.size(),
the positioning operation fails[.](#spanbuf.virtuals-5.sentence-1)
Otherwise, the function computesoff_type newoff = baseoff + off; and assigns xbeg + newoff to the next pointer xnext[.](#spanbuf.virtuals-5.sentence-2)
[6](#spanbuf.virtuals-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10362)
*Returns*: pos_type(off_type(-1)) if the positioning operation fails;pos_type(newoff) otherwise[.](#spanbuf.virtuals-6.sentence-1)
[🔗](#lib:seekpos,basic_spanbuf)
`pos_type seekpos(pos_type sp, ios_base::openmode which = ios_base::in | ios_base::out) override;
`
[7](#spanbuf.virtuals-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10374)
*Effects*: Equivalent to:return seekoff(off_type(sp), ios_base::beg, which);
[🔗](#lib:setbuf,basic_spanbuf)
`basic_streambuf<charT, traits>* setbuf(charT* s, streamsize n) override;
`
[8](#spanbuf.virtuals-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10388)
*Effects*: Equivalent to:this->span(std::span<charT>(s, n));return this;
### [31.9.4](#ispanstream) Class template basic_ispanstream [[ispanstream]](ispanstream)
#### [31.9.4.1](#ispanstream.general) General [[ispanstream.general]](ispanstream.general)
[🔗](#lib:basic_ispanstream)
namespace std {template<class charT, class traits = char_traits<charT>>class basic_ispanstream : public basic_istream<charT, traits> {public:using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [[ispanstream.cons]](#ispanstream.cons "31.9.4.2Constructors"), constructorsexplicit basic_ispanstream(std::span<charT> s,
ios_base::openmode which = ios_base::in);
basic_ispanstream(const basic_ispanstream&) = delete;
basic_ispanstream(basic_ispanstream&& rhs); template<class ROS> explicit basic_ispanstream(ROS&& s);
basic_ispanstream& operator=(const basic_ispanstream&) = delete;
basic_ispanstream& operator=(basic_ispanstream&& rhs); // [[ispanstream.swap]](#ispanstream.swap "31.9.4.3Swap"), swapvoid swap(basic_ispanstream& rhs); // [[ispanstream.members]](#ispanstream.members "31.9.4.4Member functions"), member functions basic_spanbuf<charT, traits>* rdbuf() const noexcept;
std::span<const charT> span() const noexcept; void span(std::span<charT> s) noexcept; template<class ROS> void span(ROS&& s) noexcept; private: basic_spanbuf<charT, traits> *sb*; // *exposition only*};}
[1](#ispanstream.general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10440)
[*Note [1](#ispanstream.general-note-1)*:
Constructing an ispanstream from a [*string-literal*](lex.string#nt:string-literal "5.13.5String literals[lex.string]") includes the termination character '\0' in the underlying spanbuf[.](#ispanstream.general-1.sentence-1)
— *end note*]
#### [31.9.4.2](#ispanstream.cons) Constructors [[ispanstream.cons]](ispanstream.cons)
[🔗](#lib:basic_ispanstream,constructor)
`explicit basic_ispanstream(std::span<charT> s, ios_base::openmode which = ios_base::in);
`
[1](#ispanstream.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10455)
*Effects*: Initializes the base class withbasic_istream<charT, traits>(addressof(*sb*)) and *sb* withbasic_spanbuf<charT, traits>(s, which | ios_base::in) ([[spanbuf.cons]](#spanbuf.cons "31.9.3.2Constructors"))[.](#ispanstream.cons-1.sentence-1)
[🔗](#lib:basic_ispanstream,constructor_)
`basic_ispanstream(basic_ispanstream&& rhs);
`
[2](#ispanstream.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10469)
*Effects*: Initializes the base class with std::move(rhs) and *sb* with std::move(rhs.*sb*)[.](#ispanstream.cons-2.sentence-1)
Next, basic_istream<charT, traits>::set_rdbuf(addressof(*sb*)) is called
to install the contained basic_spanbuf[.](#ispanstream.cons-2.sentence-2)
[🔗](#lib:basic_ispanstream,constructor__)
`template<class ROS> explicit basic_ispanstream(ROS&& s)
`
[3](#ispanstream.cons-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10483)
*Constraints*: ROS models ranges::[borrowed_range](range.range#concept:borrowed_range "25.4.2Ranges[range.range]")[.](#ispanstream.cons-3.sentence-1)
![convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<ROS, std::span<charT>> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<ROS, std::span<charT const>> is true[.](#ispanstream.cons-3.sentence-2)
[4](#ispanstream.cons-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10489)
*Effects*: Let sp be std::span<const charT>(std::forward<ROS>(s))[.](#ispanstream.cons-4.sentence-1)
Equivalent to:basic_ispanstream(std::span<charT>(const_cast<charT*>(sp.data()), sp.size()))
#### [31.9.4.3](#ispanstream.swap) Swap [[ispanstream.swap]](ispanstream.swap)
[🔗](#lib:swap,basic_ispanstream)
`void swap(basic_ispanstream& rhs);
`
[1](#ispanstream.swap-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10506)
*Effects*: Equivalent to:basic_istream<charT, traits>::swap(rhs);*sb*.swap(rhs.*sb*);
[🔗](#lib:swap,basic_ispanstream_)
`template<class charT, class traits>
void swap(basic_ispanstream<charT, traits>& x, basic_ispanstream<charT, traits>& y);
`
[2](#ispanstream.swap-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10522)
*Effects*: Equivalent to x.swap(y)[.](#ispanstream.swap-2.sentence-1)
#### [31.9.4.4](#ispanstream.members) Member functions [[ispanstream.members]](ispanstream.members)
[🔗](#lib:rdbuf,basic_ispanstream)
`basic_spanbuf<charT, traits>* rdbuf() const noexcept;
`
[1](#ispanstream.members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10535)
*Effects*: Equivalent to:return const_cast<basic_spanbuf<charT, traits>*>(addressof(*sb*));
[🔗](#lib:span,basic_ispanstream)
`std::span<const charT> span() const noexcept;
`
[2](#ispanstream.members-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10549)
*Effects*: Equivalent to: return rdbuf()->span();
[🔗](#lib:span,basic_ispanstream_)
`void span(std::span<charT> s) noexcept;
`
[3](#ispanstream.members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10560)
*Effects*: Equivalent to rdbuf()->span(s)[.](#ispanstream.members-3.sentence-1)
[🔗](#ispanstream.members-itemdecl:4)
`template<class ROS> void span(ROS&& s) noexcept;
`
[4](#ispanstream.members-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10570)
*Constraints*: ROS models ranges::[borrowed_range](range.range#concept:borrowed_range "25.4.2Ranges[range.range]")[.](#ispanstream.members-4.sentence-1)
(![convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<ROS, std::span<charT>>) && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<ROS, std::span<const charT>> is true[.](#ispanstream.members-4.sentence-2)
[5](#ispanstream.members-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10576)
*Effects*: Let sp be std::span<const charT>(std::forward<ROS>(s))[.](#ispanstream.members-5.sentence-1)
Equivalent to:this->span(std::span<charT>(const_cast<charT*>(sp.data()), sp.size()));
### [31.9.5](#ospanstream) Class template basic_ospanstream [[ospanstream]](ospanstream)
#### [31.9.5.1](#ospanstream.general) General [[ospanstream.general]](ospanstream.general)
[🔗](#lib:basic_ospanstream)
namespace std {template<class charT, class traits = char_traits<charT>>class basic_ospanstream : public basic_ostream<charT, traits> {public:using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [[ospanstream.cons]](#ospanstream.cons "31.9.5.2Constructors"), constructorsexplicit basic_ospanstream(std::span<charT> s,
ios_base::openmode which = ios_base::out);
basic_ospanstream(const basic_ospanstream&) = delete;
basic_ospanstream(basic_ospanstream&& rhs);
basic_ospanstream& operator=(const basic_ospanstream&) = delete;
basic_ospanstream& operator=(basic_ospanstream&& rhs); // [[ospanstream.swap]](#ospanstream.swap "31.9.5.3Swap"), swapvoid swap(basic_ospanstream& rhs); // [[ospanstream.members]](#ospanstream.members "31.9.5.4Member functions"), member functions basic_spanbuf<charT, traits>* rdbuf() const noexcept;
std::span<charT> span() const noexcept; void span(std::span<charT> s) noexcept; private: basic_spanbuf<charT, traits> *sb*; // *exposition only*};}
#### [31.9.5.2](#ospanstream.cons) Constructors [[ospanstream.cons]](ospanstream.cons)
[🔗](#lib:basic_ospanstream,constructor)
`explicit basic_ospanstream(std::span<charT> s,
ios_base::openmode which = ios_base::out);
`
[1](#ospanstream.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10635)
*Effects*: Initializes the base class withbasic_ostream<charT, traits>(addressof(*sb*)) and *sb* withbasic_spanbuf<charT, traits>(s, which | ios_base::out) ([[spanbuf.cons]](#spanbuf.cons "31.9.3.2Constructors"))[.](#ospanstream.cons-1.sentence-1)
[🔗](#lib:basic_ospanstream,constructor_)
`basic_ospanstream(basic_ospanstream&& rhs) noexcept;
`
[2](#ospanstream.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10649)
*Effects*: Initializes the base class with std::move(rhs) and *sb* with std::move(rhs.*sb*)[.](#ospanstream.cons-2.sentence-1)
Next, basic_ostream<charT, traits>::set_rdbuf(addressof(*sb*)) is called to install the contained basic_spanbuf[.](#ospanstream.cons-2.sentence-2)
#### [31.9.5.3](#ospanstream.swap) Swap [[ospanstream.swap]](ospanstream.swap)
[🔗](#lib:swap,basic_ospanstream)
`void swap(basic_ospanstream& rhs);
`
[1](#ospanstream.swap-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10665)
*Effects*: Equivalent to:basic_ostream<charT, traits>::swap(rhs);*sb*.swap(rhs.*sb*);
[🔗](#lib:swap,basic_ospanstream_)
`template<class charT, class traits>
void swap(basic_ospanstream<charT, traits>& x, basic_ospanstream<charT, traits>& y);
`
[2](#ospanstream.swap-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10681)
*Effects*: Equivalent to x.swap(y)[.](#ospanstream.swap-2.sentence-1)
#### [31.9.5.4](#ospanstream.members) Member functions [[ospanstream.members]](ospanstream.members)
[🔗](#lib:rdbuf,basic_ospanstream)
`basic_spanbuf<charT, traits>* rdbuf() const noexcept;
`
[1](#ospanstream.members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10694)
*Effects*: Equivalent to:return const_cast<basic_spanbuf<charT, traits>*>(addressof(*sb*));
[🔗](#lib:span,basic_ospanstream)
`std::span<charT> span() const noexcept;
`
[2](#ospanstream.members-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10708)
*Effects*: Equivalent to: return rdbuf()->span();
[🔗](#lib:span,basic_ospanstream_)
`void span(std::span<charT> s) noexcept;
`
[3](#ospanstream.members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10719)
*Effects*: Equivalent to rdbuf()->span(s)[.](#ospanstream.members-3.sentence-1)
### [31.9.6](#spanstream) Class template basic_spanstream [[spanstream]](spanstream)
#### [31.9.6.1](#spanstream.general) General [[spanstream.general]](spanstream.general)
[🔗](#lib:basic_spanstream)
namespace std {template<class charT, class traits = char_traits<charT>>class basic_spanstream : public basic_iostream<charT, traits> {public:using char_type = charT; using int_type = typename traits::int_type; using pos_type = typename traits::pos_type; using off_type = typename traits::off_type; using traits_type = traits; // [[spanstream.cons]](#spanstream.cons "31.9.6.2Constructors"), constructorsexplicit basic_spanstream(std::span<charT> s,
ios_base::openmode which = ios_base::out | ios_base::in);
basic_spanstream(const basic_spanstream&) = delete;
basic_spanstream(basic_spanstream&& rhs);
basic_spanstream& operator=(const basic_spanstream&) = delete;
basic_spanstream& operator=(basic_spanstream&& rhs); // [[spanstream.swap]](#spanstream.swap "31.9.6.3Swap"), swapvoid swap(basic_spanstream& rhs); // [[spanstream.members]](#spanstream.members "31.9.6.4Member functions"), members basic_spanbuf<charT, traits>* rdbuf() const noexcept;
std::span<charT> span() const noexcept; void span(std::span<charT> s) noexcept; private: basic_spanbuf<charT, traits> *sb*; // *exposition only*};}
#### [31.9.6.2](#spanstream.cons) Constructors [[spanstream.cons]](spanstream.cons)
[🔗](#lib:basic_spanstream,constructor)
`explicit basic_spanstream(std::span<charT> s,
ios_base::openmode which = ios_base::out | ios_bas::in);
`
[1](#spanstream.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10774)
*Effects*: Initializes the base class withbasic_iostream<charT, traits>(addressof(*sb*)) and *sb* withbasic_spanbuf<charT, traits>(s, which) ([[spanbuf.cons]](#spanbuf.cons "31.9.3.2Constructors"))[.](#spanstream.cons-1.sentence-1)
[🔗](#lib:basic_spanstream,constructor_)
`basic_spanstream(basic_spanstream&& rhs);
`
[2](#spanstream.cons-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10788)
*Effects*: Initializes the base class with std::move(rhs) and *sb* with std::move(rhs.*sb*)[.](#spanstream.cons-2.sentence-1)
Next, basic_iostream<charT, traits>::set_rdbuf(addressof(*sb*)) is called to install the contained basic_spanbuf[.](#spanstream.cons-2.sentence-2)
#### [31.9.6.3](#spanstream.swap) Swap [[spanstream.swap]](spanstream.swap)
[🔗](#lib:swap,basic_spanstream)
`void swap(basic_spanstream& rhs);
`
[1](#spanstream.swap-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10804)
*Effects*: Equivalent to:basic_iostream<charT, traits>::swap(rhs);*sb*.swap(rhs.*sb*);
[🔗](#lib:swap,basic_spanstream_)
`template<class charT, class traits>
void swap(basic_spanstream<charT, traits>& x, basic_spanstream<charT, traits>& y);
`
[2](#spanstream.swap-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10820)
*Effects*: Equivalent to x.swap(y)[.](#spanstream.swap-2.sentence-1)
#### [31.9.6.4](#spanstream.members) Member functions [[spanstream.members]](spanstream.members)
[🔗](#lib:rdbuf,basic_spanstream)
`basic_spanbuf<charT, traits>* rdbuf() const noexcept;
`
[1](#spanstream.members-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10833)
*Effects*: Equivalent to:return const_cast<basic_spanbuf<charT, traits>*>(addressof(*sb*));
[🔗](#lib:span,basic_spanstream)
`std::span<charT> span() const noexcept;
`
[2](#spanstream.members-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10847)
*Effects*: Equivalent to: return rdbuf()->span();
[🔗](#lib:span,basic_spanstream_)
`void span(std::span<charT> s) noexcept;
`
[3](#spanstream.members-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iostreams.tex#L10858)
*Effects*: Equivalent to rdbuf()->span(s)[.](#spanstream.members-3.sentence-1)