Почему std::move не [[nodiscard]] в С++ 20?

Недавно я прочитал о [[nodiscard]] в C++17, и, насколько я понимаю, это новая функция (дизайн по контракту?), которая заставляет вас использовать возвращаемое значение. Это имеет смысл для спорных функций, таких как std::launder (nodiscard начиная с C++20), но мне интересно, почему std::move не определено так в C++17/20. Знаете ли вы вескую причину или это потому, что С++ 20 еще не завершен?


person bbalchev    schedule 20.04.2019    source источник
comment
Я знаю причину, которая имеет для меня смысл, но если нет официального документа, прямо говорящего, почему это не так, это просто превращает вопрос в основанный на мнении.   -  person Sebastian Redl    schedule 20.04.2019
comment
Как вы думаете, почему std::move не обязательно должен быть [[nodiscard]]?   -  person bbalchev    schedule 20.04.2019
comment
Потому что абсолютно ничего плохого (или вообще) не происходит, когда вы его не используете.   -  person Sebastian Redl    schedule 20.04.2019
comment
@SebastianRedl: точно так же ничего полезного не происходит. Это то же самое, что написать пустой оператор, поэтому [[nodiscard]] поможет диагностировать ошибки. Кроме того, ничего страшного не происходит, когда vector::empty() игнорируется, но по понятным причинам помечается как [[nodiscard]].   -  person Vittorio Romeo    schedule 20.04.2019
comment
Вы можете написать и отправить документ с предложением, чтобы добавить его :)   -  person Jesper Juhl    schedule 20.04.2019
comment
@SebastianRedl Звучит как отличная причина поставить отметку [[nodiscard]]: Эй, ты сделал что-то совершенно бессмысленное. Вы хотели сделать что-то еще?   -  person Barry    schedule 20.04.2019
comment
@SebastianRedl это не совсем правильно. Говорят, что объекты находятся в допустимом, но неопределенном состоянии, и для них можно безопасно использовать только оператор присваивания. Так что ничего страшного (или вообще) не происходит на мой взгляд.   -  person bbalchev    schedule 20.04.2019
comment
@bbalchev std::move не двигается. Прохождение объекта через std::move и игнорирование результата абсолютно ничего не делает.   -  person tkausl    schedule 21.04.2019
comment
Конечно, но вы не можете использовать параметр, который вы дали std::move, кроме operator=, так что это все еще ошибка, не так ли?   -  person bbalchev    schedule 21.04.2019
comment
@bbalchev Отдельный std::move(x); не работает.   -  person L. F.    schedule 21.04.2019
comment
@bbalchev Все, что делает std::move, это возвращает ссылку rvalue на объект; так что объект может впоследствии быть перемещен из если ссылка используется таким образом.   -  person Sebastian Redl    schedule 21.04.2019
comment
Вы можете сделать свой собственный bbalchev::move, на котором есть [[nodiscard]]. Я бы назвал своего eljay::move_dammit, но это только я.   -  person Eljay    schedule 04.05.2019


Ответы (2)


Насколько я знаю, P0600R1 является единственным предложением для добавление [[nodiscard]] в стандартную библиотеку, которая применялась к C++20. Из этой бумаги:

Мы предлагаем консервативный подход:

[...]

Его не следует добавлять, когда:

  • [...]
  • неиспользование возвращаемого значения не имеет смысла, но не вредит и обычно не является ошибкой
  • [...]

Итак, [[nodiscard]] не должен сигнализировать о плохом коде, если это

  • [...]
  • не больно и наверное не имелось в виду изменение состояния что не бывает

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

person cpplearner    schedule 20.04.2019
comment
Не знаю. Неиспользование возвращаемого значения std::move всегда является ошибкой в ​​моей книге, и поэтому согласно вашей цитате его не следует отбрасывать: либо подразумевается, что пользователь забыл использовать возвращаемое значение, либо вызов не нужен, поскольку он не имеет никакого эффекта. . - person Konrad Rudolph; 21.04.2019
comment
@KonradRudolph: Никто, по-видимому, не показал комитету распространенный случай, когда отсутствие nodiscard в std::move() вызывает фактические ошибки. Рассмотрите возможность поднять этот вопрос в списке рассылки обсуждения стандартов C++. - person einpoklum; 02.04.2020
comment
@einpoklum Предположительно, как и другие, я не считаю этот вопрос достаточно срочным, чтобы тратить на него время комитета (новых предложений и так слишком много). Все, что я говорю, это то, что отсутствие [[nodiscard]] является вероятно недосмотром, а не сознательным решением, мотивированным цитатой в этом ответе. - person Konrad Rudolph; 02.04.2020

Команда стандартной библиотеки MSVC пошла дальше и добавила несколько тысяч экземпляров [[nodiscard]] начиная с VS 2017 15.6 и сообщила о невероятном успехе (как с точки зрения обнаружения большого количества ошибок, так и с точки зрения отсутствия жалоб пользователей). Критерии, которые они описали, были примерно такими:

  1. Чистые наблюдатели, т.е. vector::size(), vector::empty и даже std::count_if()
  2. Вещи, которые приобретают сырые ресурсы, например. allocate()
  3. Функции, в которых отбрасывание возвращаемого значения с большой вероятностью приведет к неправильному коду, например. std::remove()

MSVC помечает std::move() и std::forward() как [[nodiscard]] в соответствии с этими критериями.

Хотя это официально не аннотировано как таковое в стандарте, похоже, оно обеспечивает очевидную пользу для пользователя, и это скорее вопрос создания такого документа, чтобы отметить все правильные вещи [[nodiscard]] (опять же, несколько тысяч экземпляров из MSVC) и применить их - это сама по себе работа не сложная, но объем большой. А пока, может быть, подтолкнете вашего любимого поставщика стандартной библиотеки и попросите его сделать [[nodiscard]] кучу всего?

person Barry    schedule 20.04.2019