std:: ignore pour ignorer la variable non utilisée

Est-il une bonne méthode à utiliser std::ignore pour ignorer les variables inutilisées?

Supposons que j'ai une fonction comme ceci:

void func(int i)
{
   //for some reason, I don't need i anymore but I cannot change signature of function    
   std::ignore = i; 
}

Renseignements Supplémentaires

il s'agissait d'un exemple et certaines réponses suggéraient d'utiliser anonyme variables. Mais comment le faire pour d'autres cas, comme:

int Thread_UnSafe_func_returnSomething():
void func()
{
   // To make it thread safe
   // Also it is required to call only once
   static int i = Thread_UnSafe_func_returnSomething();

   std::ignore = i;
}
32
demandé sur Mailerdaimon 2016-09-28 14:12:21

6 réponses

dans ce cas, n'écrivez pas le nom de la variable:

void func(int /*i*/)
{
    ...
}

pour une question mise à jour, j'opterais pour une instance statique d'une classe avec initialisation nécessaire dans un constructeur. Je dis initialisation parce que la seule raison que je peux faire pour avoir une telle fonction est de initialise un objet global.

class SomethingInitializer {
public:
    SomethingInitializer() {
        func_returnSomething();
    }
    ~SomethingInitializer() {
        // Note, that when you initialize something it is a good practice to deinitialize it at the end, and here is a proper place for that.
    }
};

void func() {
    static SomethingInitializer initializer;
}

cette solution a un petit bonus: SomethingInitializer est conforme à la RAII. Ainsi, lorsque l'application termine destructor est appelé et il peut faire la désinitialisation.

notez, que le compilateur sait que les classes peuvent faire quelque chose d'utile dans le constructeur et le destructeur, donc il ne se plaindra pas pour la variable inutilisée.

40
répondu Alexey Guseynov 2016-09-28 12:51:00

std::ignore peut fonctionner mais il est destiné à être utilisé pour les tuples. Vous devez donc inclure l'en-tête tuple et qui sait quelles opérations sont effectuées pour la tâche. Cela peut aussi casser dans une autre version c++ parce qu'elle n'a jamais été documentée pour être utilisée de cette façon.

une meilleure façon pour cela est l'attribut C++17 [[maybe_unused]]

void func([[maybe_unused]] int i)
{
}

il place la déclaration directement à la déclaration variable, de sorte que vous n'avez pas à la déclarer dans une ligne/déclaration supplémentaire.

la même chose peut être utilisée pour les variables locales (et locales-statiques)

...
[[maybe_unused]] static int a = something();
...

Et aussi pour beaucoup d'autres:

Apparaît dans la déclaration d'une classe, d'une définition de type, une variable, un non membre de données, une fonction, une énumération ou un agent recenseur. Si le compilateur émet des avertissements inutilisés entités, cet avertissement est supprimé pour toute entité déclarée non utilisée.

voir http://en.cppreference.com/w/cpp/language/attributes

quant aux personnes concernées que vous pouvez toujours utiliser les variables après les avoir déclarées inutilisées:

Oui, c'est possible, mais (au moins avec clang), vous obtiendrez des mises en garde dans le cas où vous utilisez maybe_unused variables déclarées.

35
répondu Hayt 2016-09-29 08:19:07

std::ignorer n'était pas destiné à être utilisé à cet effet:

un objet de type non spécifié tel que n'importe quelle valeur puisse lui être assignée sans effet. Destiné à être utilisé avec std::tie lors du déballage d'un std::tuple, comme un placeholder pour les arguments qui ne sont pas utilisés.


je vous suggère de faites ce que vous pensez, car dans un grand projet réel, il mènera à un code qui est plus difficile à maintain, où on regarderait le prototype d'une fonction, verrait qu'il prend un argument int i, mais la fonction n'aurait pas besoin de cela en réalité-ne se sent pas bien, n'est-ce pas? :)

15
répondu gsamaras 2016-09-28 17:35:08

Comme alternative, sans enlever i à partir de la signature (comme certains outils de documentation susceptibles d'en avoir besoin), il y a plusieurs façons de le silence de l'avertissement:

void func(int i)
{
   static_cast<void>(i); // Silent warning for unused variable
}

il n'est pas entièrement portable, mais cela rend muet l'avertissement sur la plupart des compilateurs.

Le propre est de créer une fonction dédiée pour que:

template <typename T>
void Unused(T&& /*No name*/) { /*Empty*/ }

et

void func(int i)
{
   Unused(i); // Silent warning for unused variable
}
8
répondu Jarod42 2016-09-28 11:59:23

je pense que vous avez un problème XY ici. Vous ne vous souciez pas vraiment de la façon d'ignorer les variables statiques; vous voulez juste appeler une fonction une fois (et seulement une fois) d'une manière thread-safe, reentrant.

ce à quoi je dis: Avez-vous entendu parler de std::call_once? Vous devez réécrire votre méthode

#include <mutex>

int Thread_UnSafe_func_returnSomething();
void func(void)
{
      //To make it thread safe
     static std::once_flag initComplete;
     std::call_once(initComplete, func_returnSomething);
 }
2
répondu Jacob Manaker 2016-09-28 16:14:02

une autre façon de le faire est d'utiliser le type de retour suivant:

auto func(int i) -> decltype(void(i)) {}
int main() {}

Si vous avez plus d'une variable, vous pouvez les énumérer:

auto func(int i, int j) -> decltype(void(i), void(j)) {}
int main() {}

et vous pouvez toujours déclarer votre type de retour préféré si void n'est pas ce que vous voulez:

auto func(int i) -> decltype(void(i), int{}) { return 42; }
int main() {}

les avantages de cette solution sont:

  • le nom de la Variable est préservé: comme mentionné par d'autres, ne donnez pas de nom à la variable ne pourrait pas être option (à cause de votre système de documentation, par exemple).

  • vous ne polluerez pas votre corps fonctionnel avec des expressions inutiles visant à taire quelques avertissements.

  • il n'est pas nécessaire de définir explicitement la fonction de support pour cela.

bien sûr, cela ne s'applique pas aux variables statiques déclarées dans le corps de la fonction, mais vous pouvez faire quelque chose de similaire en revenant de la fonction (juste un exemple):

int f() {
    static int i = 0;
    static int j = 0;
    return void(i), void(j), 42;
}

int main () {}

Plus ou moins les mêmes avantages.

1
répondu skypjack 2016-09-28 17:53:35