Std:: stringstream и метод str

Я заметил что-то при попытке использовать объект stringstream. Вот бесполезный пример, чтобы объяснить это:

stringstream ss ;
ss << "my string" ;
cout << ss.str() << endl ;

Не эквивалентен

cout << (stringstream() << "my string").str() << endl ;

Это приводит к ошибке компиляции, в которой говорится, что "class std:: basic_ostream не имеет имени с именем str.

Я не могу это легко объяснить. Это не критично для моего приложения, но я уверен, что это скрывает трюк С++, который нужно понять.

Примечание: я использую gcc с С++ 14

Ответы

Ответ 1

operator<< не определен для std::stringstream, но для его базового класса std::ostream, поэтому он не возвращает ссылку на std::stringstream и, следовательно, метод str() ( который является методом std::stringstream), не найден.

Технически, это на самом деле std::basic_stringstream<CharT,Traits> и std::basic_ostream<CharT,Traits>, но вы получаете идею:)

Ответ 2

Проблема с этим:

cout << (stringstream() << "my string").str() << endl;

Это выражение stringstream() << "my string" возвращает объект std::ostream&, а не std::stringstream.

Вы можете исправить это, указав некоторые соответствующие перегрузки:

template<typename Type>
std::stringstream& operator<<(std::stringstream& ss, const Type& type)
{
    static_cast<std::ostream&>(ss) << type;
    return ss;
}

template<typename Type>
std::stringstream& operator<<(std::stringstream&& ss, const Type& type)
{
    static_cast<std::ostream&>(ss) << type;
    return ss;
}

template<typename Type>
std::stringstream& operator>>(std::stringstream& ss, Type& type)
{
    static_cast<std::istream&>(ss) >> type;
    return ss;
}

template<typename Type>
std::stringstream& operator>>(std::stringstream&& ss, Type& type)
{
    static_cast<std::istream&>(ss) >> type;
    return ss;
}

Теперь, когда вы используете операторы << и >> для объекта std::stringstream, он будет вызывать эти перегрузки, и они возвратят std::stringstream&, чтобы вы могли напрямую использовать его интерфейс.