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