§27.7.3.9 определяет следующую перегрузку для operator<<:
template <class charT, class traits, class T>
basic_ostream<charT, traits>&
operator<<(basic_ostream<charT, traits>&& os, const T& x);
Эффекты:
os << x
Возвращает:os
(§27.7.2.6 определяет перегрузку rvalue для operator>>.)
В принципе, он просто переходит к перегрузке lvalue. Я считаю, что эта перегрузка является довольно опасной (istream еще одна, чем на самом деле ostream), рассмотрим следующее:
#include <sstream>
#include <iostream>
int main(){
auto& s = (std::stringstream() << "hi there!\n");
std::cout << s.rdbuf(); // oops
}
Пример Live на Ideone (идеальный пример поведения undefined). На MSVC10 ничего не печатает.
Приведенный выше пример может выглядеть ухищренным, но не должно быть слишком сложно попасть в эту ситуацию в общий код или при передаче (std::stringstream() << "text") функции, которая обеспечивает lvalue и rvalue-перегрузку и сохраняет std::ostream или std::istream по-разному в зависимости от перегрузки.
Теперь, что будет аргументом, снова возвращающим basic_ostream<charT, traits>&& и указав следующее?
Возвращает: move (os)
(И то же самое для basic_istream.)
Есть ли что-нибудь, что я пропускаю? В текущем состоянии, на мой взгляд, это выглядит просто опасно и как дефект. Я просмотрел список проблем LWG и нашел это предложение ( привет @HowardHinnant!). Он действительно возвращает rvalue, однако только для дополнительного преимущества того, что вы можете связать этого специального оператора, а не конкретно рассматривая проблему безопасности, описанную выше (хотя она, безусловно, ее разрешает). Кроме того, он обозначен как закрытый и для повторного рассмотрения для следующего стандарта. Таким образом, я подумал, что спрошу здесь:
Есть ли веская причина, почему вышеупомянутая перегрузка возвращает ссылку lvalue?