web-dev-qa-db-fra.com

Comment supprimer intentionnellement une valeur de retour [[nodiscard]]?

Dis que j'ai

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

int main ()
{
    foo ();
}

ensuite

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

mais si

int x = foo ();

ensuite

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

Existe-t-il un moyen clair de dire au compilateur "Je veux supprimer ce [[nodiscard]] valeur"?

16
spraff

Le proposition de nodiscard du WG14 discute de la raison pour laquelle le diagnostic peut être réduit au silence en coulant pour annuler. Il dit que le fait d'annuler est la manière encouragée (si non normative) de la réduire au silence, qui suit ce que l'implémentation existante fait avec __attribute__((warn_unused_result)):

L'attribut [[nodiscard]] est largement utilisé dans le monde réel, étant implémenté par Clang et GCC comme __attribute __ ((warn_unused_result)), mais a été normalisé sous le nom [[nodiscard]] par WG21. Cette proposition a choisi l'identifiant nodiscard car tout écart par rapport à ce nom créerait une incompatibilité inutile avec C++.

La sémantique de cet attribut s'appuie fortement sur la notion d'utilisation, dont la définition est laissée à l'appréciation de l'implémentation. Cependant, les conseils non normatifs spécifiés par le WG21 sont d'encourager les implémentations à émettre un diagnostic d'avertissement lorsqu'un appel de fonction nodiscard est utilisé dans une expression de valeur rejetée potentiellement évaluée, sauf s'il s'agit d'un transtypage explicite. pour annuler . Cela signifie qu'une implémentation n'est pas encouragée pour effectuer une analyse de flux de données (comme un diagnostic de variable locale initialisé mais non utilisé l'exigerait). ...

La façon C++ serait static_cast<void>.

Voir le projet de norme C++ [[ dcl.attr.nodiscard] p2 :

[Remarque: Un appel nodiscard est une expression d'appel de fonction qui appelle une fonction précédemment déclarée nodiscard, ou dont le type de retour est une classe éventuellement qualifiée par cv ou un type d'énumération marqué nodiscard. L'apparition d'un appel nodiscard en tant qu'expression de valeur rejetée potentiellement évaluée est déconseillée sauf si elle est explicitement convertie en void. Les implémentations doivent émettre un avertissement dans de tels cas. Cela est généralement dû au fait que la suppression de la valeur de retour d'un appel nodiscard a des conséquences surprenantes. - note de fin]

Ceci est une note, donc non normative, mais c'est essentiellement ce que les implémentations existantes font avec __attribute__((warn_unused_result)). Notez également qu'un diagnostic pour nodiscard est également non normatif, donc un diagnostic pour violation de nodiscard n'est pas mal formé mais une qualité de mise en œuvre tout comme la suppression via un casting pour annuler est.

voir le document clang sur nodiscard, warn_unused_result :

Clang prend en charge la possibilité de diagnostiquer lorsque les résultats d'une expression d'appel de fonction sont ignorés dans des circonstances suspectes. Un diagnostic est généré lorsqu'une fonction ou son type de retour est marqué avec [[nodiscard]] (ou __attribute __ ((warn_unused_result))) et l'appel de fonction apparaît comme une expression de valeur ignorée potentiellement évaluée qui n'est pas explicitement converti en annulation.

12
Shafik Yaghmour

Cast it to void :

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

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

Cela dit essentiellement au compilateur " Oui, je sais que je rejette cela, oui, j'en suis sûr. "

13
Sombrero Chicken

Vous pouvez également baliser le int retourné avec une autre balise:

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

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

Peut être utile si vous disposez d'un code de débogage uniquement qui requiert la valeur.

8
Matthieu Brucher