Версия оператора<< что возвращает ostringstream, а не поток


Я всегда думал, что это было бы удобно, чтобы быть в состоянии написать:

const std::string s = (std::ostringstream() << "hi" << 0).str();

Это не работает в C++ по умолчанию, потому что оператор<< возвращает ostringstream как поток, который, очевидно, не имеет (ул.) член.

Я был приятно удивлен, хотя, чтобы обнаружить, что это может быть сделано в C++11:

#include <iostream>
#include <sstream>
#include <string>

template <typename CharT, typename traits, typename T>
std::basic_ostringstream<CharT,traits>&& operator<<(std::basic_ostringstream<CharT,traits>&& out, const T& t) {
  static_cast<std::basic_ostream<CharT,traits>&>(out) << t;
  return std::move(out);
}

int main() {
  const std::string s = (std::ostringstream() << "hi" << 0).str();
  std::cout << s << std::endl;
}

Он должен ссылки rvalue и семантику перемещения, чтобы связать временные ссылки здесь.

  1. Есть ли хорошая причина, почему это не предусмотрено стандартной библиотеки по умолчанию? Это недосмотр? Делая этот правовой кодекс идиома кажется, что он может предложить ряд преимуществ.
  2. В мой локальный проект C++11, я приведу некоторые "полезности" код. Есть ли причина, почему я не должен включать этот и использовать его повсеместно?

Как насчет более универсальный вариант:

template <typename S, typename T, class = typename
               std::enable_if<std::is_base_of<std::basic_ostream<typename S::char_type,typename S::traits_type>, S>::value>::type>
S&& operator<<(S&& out, const T& t) {
  static_cast<std::basic_ostream<typename S::char_type,typename S::traits_type>&>(out) << t;
  return std::move(out);
}


2174
8
задан 16 ноября 2011 в 11:11 Источник Поделиться
Комментарии
4 ответа

Бьярне дает довольно лаконичное описание того, почему этот (и многие похожие) функции не в стандарте. Он указывает на то, что практически все, кто разговаривает с ним о C++ по сути то же самое, что сказать: "C++ - это путь к большим и слишком сложным. Вы должны действительно работать на много меньше и проще. Но в то время как вы на него, вы должны добавить это одна очень интересная особенность, я думал"

Это напоминает мне о вещах, которые я видел о том, как вопросы политические выборы могут быть сформулированы. Если я спрошу: "вы думаете, что эта страна должна сделать больше, чтобы [увеличение рабочих мест | помощь нуждающимся | и т. д.]?" Я могу рассчитывать на значительное большинство людей, говоря "да". Если я спрашиваю "как вы думаете, мы должны повышать налоги на Х%?", Я могу рассчитывать на столь же подавляющее большинство говорит "Нет". Я могу дать почти гарантированный результат моего опроса, просто выбрать, стоит ли спрашивать о желаемых результатов или затрат.

Итог: каждую функцию вы добавляете имеет стоимость, и ориентируясь на результат не удалить стоимость. Чтобы разработать полезную языка/библиотеки, необходимо ограничить функций, чтобы те немногие, которые обеспечивают максимальный положительный результат при самых низких затратах. В случае с C++ комитет, они были довольно ясно о нескольких вещах, и одна заключается в том, что большинство новых функций вряд ли будет считаться, если они позволяют довольно существенные улучшения в коде, который использует новую функцию и имеют очень минимальную стоимость, особенно с точки зрения нарушения каких-либо существующий код.

6
ответ дан 16 ноября 2011 в 04:11 Источник Поделиться

Его хороший трюк. Но я не вижу, что он покупает вас.

Так что у вас есть объект std::string объект, который вы сейчас используете.

int main() {
const std::string s = (std::ostringstream() << "hi" << 0).str();
std::cout << s << std::endl;
}

В C++03, Я бы с std::stringstream объект, который я сейчас использую (которые затем могут быть использованы в том же месте, что и std::string объект).

int main()
{
std::ostringstream message;
message << "hi" << 0; // one extra line.
std::cout << message.str() << std::endl;
}

Я не вижу преимущество. Может, если вы можете показать код используется в более широком контексте, где это дает преимущество над std::stringstream.

2
ответ дан 16 ноября 2011 в 11:11 Источник Поделиться


Есть ли хорошая причина, почему это не предусмотрено стандартной библиотеки по умолчанию? Это недосмотр? Делая этот правовой кодекс идиома кажется, что он может предложить ряд преимуществ.

Кроме того, что стандарт уже был ~задержано 5 лет, и эта маленькая хитрость в конечном итоге не покупать вам много?

Есть миллионы симпатичных небольших хитростей и удобство функций, которые могут быть написаны в C++. Для одного из них, чтобы получить стандартизированы, они могут предложить довольно значительную пользу.

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

2
ответ дан 16 ноября 2011 в 12:11 Источник Поделиться

Чтобы добавить к существующему ответы, это был уже полу-можно:

const std::string s = static_cast<std::ostringstream&>(
std::ostringstream() << "hi" << 0
).str();

Засунуть в #определить , и вы Золотой...

... но не совсем. Любой оператор<< реализаций, которые свободные функции, а не функции-члены не удастся, потому что их ЛХС операнд должен быть с std::ostringstream& и, как справ-к-Несопи, это позволит не привязываться к временным и std::ostringstream().

Почти забавно результате приведенного выше примера заключается в том, что ов будет содержать текст типа "0x804947c0", но поменяв "привет" и 0 в результате поведение вы ожидаете ("0hi").

1
ответ дан 18 января 2013 в 06:01 Источник Поделиться