§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?