Используйте анонимный поток строк для создания строки

Я хочу читать прямо в строку с кодом, подобным этому:

std::string myString(( std::ostringstream() << myInt << " "<< myFloat << " "<< std::boolalpha << myBool ).str());

Но VS2012 дает мне жалобу, что basic_ostream не имеет str() метод.

Есть ли способ сделать это с анонимным потоком строк?

5

Решение

operator<< для потоков возвращается std::ostream & который не имеет str() функция-член. Вам нужно использовать приведение.

static_cast<std::ostringstream&>(std::ostringstream() << etc).str()

Различия между C ++ 03 и C ++ 11 при использовании временного потока!

C ++ 03

Но помните (в C ++ 03), что std::ostringstream() создает временный объект, что означает нечлен перегрузки operator<< не может быть вызван для первого << потому что все они принимают первый аргумент как std::ostream& который не может привязаться к временному объекту. Временный объект сможет вызывать единственный участник функции.

Это означает, что следующее даст вам адрес вместо строка:

static_cast<std::ostringstream&>(std::ostringstream() << "XYZ").str()

Потому что перегрузка, которая принимает char const* в качестве аргумента не является функцией-членом, который не может быть вызван, поэтому приведенный выше код в конечном итоге вызывает функцию-член, которая принимает void const* в качестве аргумента и, таким образом, "XYZ" неявно преобразуется в void const*, который печатает адрес строкового литерала.

Как только временный вызовет функцию-член, остальные << может взывать нечлен перегрузки, потому что функция-член возвращает std::ostream& который сейчас может связать с первым аргументом нечлен перегрузки operator<<, Так что следующий код будет печатать адрес (вместо "XYZ") с последующей строкой "ABC":

static_cast<std::ostringstream&>(std::ostringstream() << "XYZ" << "ABC").str()

Демо онлайн:

C ++ 11

В C ++ 11 эта проблема была исправлена ​​путем добавления функции, не являющейся членом (27.7.3.9), которая принимает первый аргумент в качестве ссылки на rvalue, который затем перенаправляет вызов соответствующей функции, членской или неучастной. Так что печатает XYZ с последующим ABC:

13

Другие решения

basic_osstream::operator<< возвращает basic_ostreamне ostringstream, Компилятор не врет вам.

Я бы предпочел создать устройство типа StringBuilder.

class StringBuilder
{
public:
template <typename T> inline StringBuilder& operator<<(const T& t)
{
mStream << t;
return * this;
}
inline std::string get() const
{
return mStream.str();
}
inline operator std::string () const
{
return get();
}
private:
std::stringstream mStream;
};

Теперь вы можете:

std::string myString (StringBuilder() << myInt << " " << myFloat /*...*/);

В Boost также есть похожие устройства — вам лучше использовать их, если они вам доступны.

5

По вопросам рекламы [email protected]