Как я могу получить длину буфера const string без копирования или поиска?
У меня есть const std::stringstream
и желание узнать, сколько байтов содержится в его базовом буфере строк.
-
Я не могу seekg
до конца, tellg
, а затем seekg
вернуться к началу, потому что ни одна из этих операций не доступна const
ly.
-
Я не хочу получать str().size()
, потому что str()
возвращает копию, и это может быть не тривиальное количество данных.
Есть ли у меня хорошие варианты?
(Сам поток представлен мне как const
, только потому, что он является членом другого типа, и я получаю ссылку const
на объект этого типа. Поток представляет содержимое "документа" ", его инкапсулирующий объект представляет собой ответ CGI, и я пытаюсь создать точную строку заголовка Content-Length
HTTP из operator<<(std::ostream&, const cgi_response&)
.)
Ответы
Ответ 1
Мне никогда не нравилось потоковое буферирование, но это работает для меня:
#include <iostream>
#include <sstream>
std::stringstream::pos_type size_of_stream(const std::stringstream& ss)
{
std::streambuf* buf = ss.rdbuf();
// Get the current position so we can restore it later
std::stringstream::pos_type original = buf->pubseekoff(0, ss.cur, ss.out);
// Seek to end and get the position
std::stringstream::pos_type end = buf->pubseekoff(0, ss.end, ss.out);
// Restore the position
buf->pubseekpos(original, ss.out);
return end;
}
int main()
{
std::stringstream ss;
ss << "Hello";
ss << ' ';
ss << "World";
ss << 42;
std::cout << size_of_stream(ss) << std::endl;
// Make sure the output string is still the same
ss << "\nnew line";
std::cout << ss.str() << std::endl;
std::string str;
ss >> str;
std::cout << str << std::endl;
}
Ключ состоит в том, что rdbuf()
есть const
, но возвращает неконстантный буфер, который затем можно использовать для поиска.
Ответ 2
Если вы хотите узнать оставшийся доступный размер ввода:
#include <iostream>
#include <sstream>
std::size_t input_available(const std::stringstream& s)
{
std::streambuf* buf = s.rdbuf();
std::streampos pos = buf->pubseekoff(0, std::ios_base::cur, std::ios_base::in);
std::streampos end = buf->pubseekoff(0, std::ios_base::end, std::ios_base::in);
buf->pubseekpos(pos, std::ios_base::in);
return end - pos;
}
int main()
{
std::stringstream stream;
// Output
std::cout << input_available(stream) << std::endl; // 0
stream << "123 ";
std::cout << input_available(stream) << std::endl; // 4
stream << "567";
std::cout << input_available(stream) << std::endl; // 7
// Input
std::string s;
stream >> s;
std::cout << input_available(stream) << std::endl; // 4
stream >> s;
std::cout << input_available(stream) << std::endl; // 0
}
Это похоже на решение @Cornstalks, но правильно позиционирует входную последовательность.
Ответ 3
Это должно работать:))
#include <iostream>
#include <sstream>
#include <boost/move/move.hpp>
int main()
{
const std::stringstream ss("hello");
std::cout << boost::move(ss).str().size();
}