Я хочу читать прямо в строку с кодом, подобным этому:
std::string myString(( std::ostringstream() << myInt << " "<< myFloat << " "<< std::boolalpha << myBool ).str());
Но VS2012 дает мне жалобу, что basic_ostream
не имеет str()
метод.
Есть ли способ сделать это с анонимным потоком строк?
operator<<
для потоков возвращается std::ostream &
который не имеет str()
функция-член. Вам нужно использовать приведение.
static_cast<std::ostringstream&>(std::ostringstream() << etc).str()
Но помните (в 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()
Демо онлайн:
-std=c++11
-std=c++11
В C ++ 11 эта проблема была исправлена путем добавления функции, не являющейся членом (27.7.3.9), которая принимает первый аргумент в качестве ссылки на rvalue, который затем перенаправляет вызов соответствующей функции, членской или неучастной. Так что печатает XYZ
с последующим ABC
:
-std=c++11
-std=c++11
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 также есть похожие устройства — вам лучше использовать их, если они вам доступны.