Как я могу умышленно отказаться от возвращаемого значения [[nodiscard]]?

Скажем, у меня есть

[[nodiscard]] int foo ()
{
    return 0;
}

int main ()
{
    foo ();
}

затем

error: ignoring return value of ‘int foo(), declared with attribute nodiscard [-Werror=unused-result]

но если

int x = foo ();

затем

error: unused variable ‘x [-Werror=unused-variable]

Есть ли чистый способ сообщить компилятору "Я хочу отказаться от этого значения [[nodiscard]] "?

Ответ 1

В предложении WG14 nodiscard обсуждается обоснование, позволяющее отключить диагностику путем литья в пустоту. В нем говорится, что приведение к пустоте - это поощряемый (если не нормативный) способ заставить его замолчать, что следует за тем, что происходит с существующей реализацией с __attribute__((warn_unused_result)):

Атрибут [[nodiscard]] имеет широкое применение в реальном мире, реализуемый Clang и GCC как __attribute __ ((warn_unused_result)), но был стандартизован под названием [[nodiscard]] WG21. Это предложение выбрало идентификатор nodiscard, поскольку отклонение от этого имени создало бы ненужную несовместимость с C++.

Семантика этого атрибута в значительной степени зависит от понятия использования, определение которого остается на усмотрение реализации. Тем не менее, ненормативное руководство, установленное РГ21, заключается в том, чтобы побудить реализации испускать диагностическую диагностику, когда вызов функции нодискарда используется в потенциально выраженном выражении отбрасываемого значения, если он не является явным приведением в void. Это означает, что реализация не рекомендуется выполнять анализ потока данных (например, требуется инициализированная, но неиспользуемая локальная переменная)....

Путь C++ будет static_cast<void>.

См. Стандарт [ CN10] [[ dcl.attr.nodiscard] p2:

[Примечание: вызов nodiscard является выражением вызова функции, которое вызывает функцию, ранее объявленную nodiscard, или возвращаемый тип которой является, возможно, cv-классом или типом перечисления, отмеченным nodiscard. Появление вызова нодискарда в качестве потенциально вычисленного выражения с отброшенными значениями не рекомендуется, если явно не передать в void. Реализации должны выдать предупреждение в таких случаях. Это обычно происходит потому, что отбрасывание возвращаемого значения вызова с нодискардом имеет удивительные последствия. - конечная нота]

Это примечание, поэтому ненормативное, но в основном это то, что существующие реализации делают с __attribute__((warn_unused_result)). Кроме того, обратите внимание, что диагностика для нодискарда также не является нормативной, поэтому диагностика нарушения правил нодискарда не является плохой формой, но качество реализации, как и подавление через литье в пустоту.

см. документ clang о nodiscard, warn_unused_result:

Clang поддерживает возможность диагностики, когда результаты выражения вызова функции отбрасываются при подозрительных обстоятельствах. Диагностика генерируется, когда функция или ее тип возврата отмечена [[nodiscard]] (или __attribute __ ((warn_unused_result))), и вызов функции отображается как потенциально выверенное выражение с отбрасываемым значением , которое явно не передается в void.

Ответ 2

Бросьте его в void:

[[nodiscard]] int foo ()
{
    return 0;
}

int main ()
{
    static_cast<void>(foo());
}

Это в основном говорит компилятору "Да, я знаю, что я отбрасываю это, да, я в этом уверен".

Ответ 3

Вы также можете пометить возвращаемый int другим тегом:

[[nodiscard]] int foo ()
{
    return 0;
}

int main ()
{
    [[maybe_unused]] int i = foo ();
}

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