![](/img/trans.png)
[英]Any way to get an std::string_view from an std::ostringstream without copying?
[英]Is there a way to create a stringstream from a string_view without copying data?
我認為這是一個非常直截了當的問題。 我特別想使用std::get_time
,但它需要某種 stream 才能使用。 我在string_view
中傳遞數據,並希望避免復制它只是為了解析日期。
您可以使用 Boost.Iostreams 庫輕松做到這一點:
#include <boost/iostreams/device/array.hpp>
#include <boost/iostreams/stream.hpp>
#include <iostream>
#include <string>
int main() {
std::string_view buf{"hello\n"};
boost::iostreams::stream<boost::iostreams::basic_array_source<char>> stream(buf.begin(), buf.size());
std::string s;
stream >> s;
std::cout << s << '\n';
}
您應該可以使用std::stringstream
和std::basic_stringbuf<CharT,Traits,Allocator>::setbuf
做到這一點,但 C++ 標准破壞了它的要求:
[
setbuf
] 的效果是實現定義的:一些實現什么都不做,而一些實現清除當前用作緩沖區的std::string
成員並開始使用用戶提供的大小為n
的字符數組,其第一個元素指向通過s
,作為緩沖區和輸入/輸出字符序列。
沒有 Boost.IOstream 的替代解決方案(當你不能使用它時)。 它基於擴展 std::basic_streambuf 和 std::basic_istream。
#include <cstring>
#include <iostream>
#include <istream>
#include <string_view>
template<typename __char_type, class __traits_type >
class view_streambuf final: public std::basic_streambuf<__char_type, __traits_type > {
private:
typedef std::basic_streambuf<__char_type, __traits_type > super_type;
typedef view_streambuf<__char_type, __traits_type> self_type;
public:
/**
* These are standard types. They permit a standardized way of
* referring to names of (or names dependent on) the template
* parameters, which are specific to the implementation.
*/
typedef typename super_type::char_type char_type;
typedef typename super_type::traits_type traits_type;
typedef typename traits_type::int_type int_type;
typedef typename traits_type::pos_type pos_type;
typedef typename traits_type::off_type off_type;
typedef typename std::basic_string_view<char_type, traits_type> source_view;
view_streambuf(const source_view& src) noexcept:
super_type(),
src_( src )
{
char_type *buff = const_cast<char_type*>( src_.data() );
this->setg( buff , buff, buff + src_.length() );
}
virtual std::streamsize xsgetn(char_type* __s, std::streamsize __n) override
{
if(0 == __n)
return 0;
if( (this->gptr() + __n) >= this->egptr() ) {
__n = this->egptr() - this->gptr();
if(0 == __n && !traits_type::not_eof( this->underflow() ) )
return -1;
}
std::memmove( static_cast<void*>(__s), this->gptr(), __n);
this->gbump( static_cast<int>(__n) );
return __n;
}
virtual int_type pbackfail(int_type __c) override
{
char_type *pos = this->gptr() - 1;
*pos = traits_type::to_char_type( __c );
this->pbump(-1);
return 1;
}
virtual int_type underflow() override
{
return traits_type::eof();
}
virtual std::streamsize showmanyc() override
{
return static_cast<std::streamsize>( this->egptr() - this->gptr() );
}
virtual ~view_streambuf() override
{}
private:
const source_view& src_;
};
template<typename _char_type>
class view_istream final:public std::basic_istream<_char_type, std::char_traits<_char_type> > {
view_istream(const view_istream&) = delete;
view_istream& operator=(const view_istream&) = delete;
private:
typedef std::basic_istream<_char_type, std::char_traits<_char_type> > super_type;
typedef view_streambuf<_char_type, std::char_traits<_char_type> > streambuf_type;
public:
typedef _char_type char_type;
typedef typename super_type::int_type int_type;
typedef typename super_type::pos_type pos_type;
typedef typename super_type::off_type off_type;
typedef typename super_type::traits_type traits_type;
typedef typename streambuf_type::source_view source_view;
view_istream(const source_view& src):
super_type( nullptr ),
sb_(nullptr)
{
sb_ = new streambuf_type(src);
this->init( sb_ );
}
view_istream(view_istream&& other) noexcept:
super_type( std::forward<view_istream>(other) ),
sb_( std::move( other.sb_ ) )
{}
view_istream& operator=(view_istream&& rhs) noexcept
{
view_istream( std::forward<view_istream>(rhs) ).swap( *this );
return *this;
}
virtual ~view_istream() override {
delete sb_;
}
private:
streambuf_type *sb_;
};
int main(int argc, const char** argv)
{
std::string_view v("ABDCD\n 123\n FAG\n 456789");
view_istream<char> in( v );
std::string s;
in >> s;
std::cout << s << std::endl;
int i;
in >> i;
std::cout << i << std::endl;
in >> s;
std::cout << s << std::endl;
in >> i;
std::cout << i << std::endl;
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.