Улучшает ли безопасность безопасность операторов присваивания только как lvalue?

Если T – тип classа с сигнатурой по умолчанию для оператора присваивания, то мы можем написать:

 T const &ref = ( T{} = something ); 

который создает оборванную ссылку. Однако с подписью:

 T &operator=(T t) & 

приведенный выше код с оборванной ссылкой не сможет скомпилировать. Это предотвратит некоторые ситуации, когда мы возвращаем значение lvalue, которое обозначает временный объект – нежелательные ситуации, потому что они могут привести к оборванным ссылкам.

Есть ли причина не делать этого; мы будем отключать любые допустимые варианты использования для операторов присваивания?

Я думаю, что те же комментарии могут применяться и к составным операторам присваивания, += и т. Д. Более реалистичным может быть случай:

 std::string const &s = std::string("Hello, ") += "world!"; 

где опечатка осталась незамеченной до времени выполнения UB.

По моему опыту в редком случае вы хотите присвоить rvalue, написание

 template std::remove_reference_t& as_lvalue(T&&t){return t;} 

и выполнение as_lvalue( tmp() ) = foo вместо tmp()=foo не является огромным барьером. Это означает, что случайный бит кода, который присваивал значение rvalue, теперь сломается; Я лично подозревал бы, что большинство таких случаев на самом деле являются необработанными ошибками.


Ограничение каждого типа в std ограничено lvalue на operator= рассматривалось во время стандартизации C ++ 11 во Франкфурте (2009/07). Приведенные в протоколе рассуждения были следующими:

N2819, «Ref-Qualifiers N2819 для операторов присваивания стандартной библиотеки» изначально были рассмотрены LWG. В этом предложении было предложено изменить 350 операторов присваивания копий в стандартной библиотеке C ++ для предотвращения операций присваивания, в которых левый операнд является значением r. Из-за большого количества необходимых изменений предложение было отправлено в EWG с запросом о пересмотре поведения по умолчанию для неявных операторов присваивания копиям, так что присвоение значения r недопустимо. EWG решила сохранить статус-кво из-за опасений относительно обратной совместимости.

Я прочитал, что, говоря «350 изменений? Как насчет изменения языка?». EWG сказал: «Нет, это изменение языка может нарушить совместимость». И, возможно, предложение умерло на лозе.

В 2009 году C ++ 11 (тогда C ++ 0x) уже отставал от графика. Поскольку предложение включало 300 изменений в библиотеку, которые (теоретически) могли бы вызвать регрессии. Ни одна другая причина не упоминалась в протоколах. Это отклоняется за то, что вы не стоите боли регрессий (или даже проверки частоты регрессий!) Понятно. Поэтому я не предполагал бы предубеждения по этой идее только потому, что C ++ отклонил ее в std .