Почему оператор члена std :: string = не lvalue ref-qualified - PullRequest
1 голос
/ 10 апреля 2020

Я недавно узнал , что функции-члены могут иметь ref-квалификацию , что позволяет мне писать

struct S {
    S& operator=(S const&) & // can only be used if the implicit object is an lvalue
    { 
      return *this; 
    }
};

S operator+(S const &, S const &) { 
  return {}; 
}

, тем самым не давая пользователям делать такие вещи, как

S s{};
s + s = S{}; // error

Однако я вижу, что член std::string operator= не делает этого . Таким образом, следующий код компилируется без предупреждений

std::string s;
s + s = s;

Есть ли причина для этого?

Если нет, то можно ли было добавить квалификатор ref в будущем или это каким-то образом нарушило бы существующий код?

Ответы [ 2 ]

0 голосов
/ 10 апреля 2020

Вероятно, время играет роль в этом решении. Ref-квалифицированные функции-члены были добавлены в язык с C ++ 11, в то время как std::string существует с C ++ 98. Изменение определения чего-либо в стандартной библиотеке не является чем-то легким, поскольку это может привести к ненужному нарушению существующего кода. Это не та ситуация, когда нужно смотреть исключительно на то, почему это странное назначение должно быть разрешено (то есть искать сценарий использования). Скорее следует также взглянуть на то, почему это странное назначение следует запретить (то есть посмотреть на преимущества и взвесить их против потенциальной боли, когда в противном случае рабочий код нарушается). Как часто это изменение будет иметь значение для реализации c сценария кодирования ios?

Глядя на комментарии, счетчик одного предложенного варианта использования был "Они могли бы просто [другой подход] " Да, они могли, но что, если они не сделали? Предложение альтернатив является продуктивным при первоначальном проектировании конструкции (std::string). Однако, когда структура широко используется, вы должны учитывать существующий код, который в настоящее время не использует альтернативу. Достаточно ли пользы от боли, которую вы можете причинить? Будет ли это изменение на самом деле ловить ошибки достаточно часто? Насколько распространены такие ошибки в ситуациях, когда другое предупреждение не будет вызвано? (Например, использование присваивания вместо равенства в условном выражении if, скорее всего, уже сгенерирует предупреждение.) Это некоторые вопросы, с которыми сталкиваются разработчики языка.

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

0 голосов
/ 10 апреля 2020

Не ясно, почему стандарт не запрещает поведение, которое вы представили, но есть несколько возможных объяснений:

  1. Это просто упущение в C ++ 11. До C ++ 11 не было методов с повторной квалификацией, и поэтому кто-то забыл изменить стандарт поведения.

  2. Он сохраняется для обратной совместимости для людей, которые использовали «грязный» код вроде:

std::string("a") = "gds";

по некоторым странным причинам.

А насчет добавления этого в будущем - это было бы возможно. Но сначала старый operator= должен был бы быть устаревшим, а затем удален, потому что это привело бы к тому, что код, подобный приведенному выше, не скомпилировался. И даже тогда некоторые компиляторы, вероятно, будут поддерживать его для обратной совместимости со стандартом

...