web-dev-qa-db-fra.com

Avertissement Pedantic GCC: qualificatifs de type sur le type de retour de fonction

Lorsque j'ai compilé mon code C++ avec GCC 4.3 pour la première fois, (après l'avoir compilé avec succès sans avertissements sur 4.1, 4.0, 3.4 avec le -Wall -Wextra options) J'ai soudainement eu un tas d'erreurs de la forme warning: type qualifiers ignored on function return type.

Considérer temp.cpp:

class Something
{
public:
    const int getConstThing() const {
        return _cMyInt;
    }
    const int getNonconstThing() const {
        return _myInt;
    }

    const int& getConstReference() const {
        return _myInt;
    }
    int& getNonconstReference() {
        return _myInt;
    }

    void setInt(const int newValue) {
        _myInt = newValue;
    }

    Something() : _cMyInt( 3 ) {
        _myInt = 2;
    }
private:
    const int _cMyInt;
    int _myInt;
};

Fonctionnement g++ temp.cpp -Wextra -c -o blah.o:

temp.cpp:4: warning: type qualifiers ignored on function return type
temp.cpp:7: warning: type qualifiers ignored on function return type

Quelqu'un peut-il me dire ce que je fais mal qui viole la norme C++? Je suppose que lors du retour par valeur, le premier const est superflu, mais j'ai du mal à comprendre pourquoi il est nécessaire de générer un avertissement avec lui. Y a-t-il d'autres endroits où je devrais laisser la const?

66
Seth Johnson

Cela ne viole pas la norme. C'est pourquoi ils sont avertissements et non erreurs.

Et en effet, vous avez raison - le premier const est superflu. Le compilateur vous avertit parce que vous avez ajouté du code qui, dans d'autres circonstances, pourrait signifier quelque chose, mais dans ce cas, cela ne veut rien dire, et il veut s'assurer que vous ne serez pas déçu plus tard lorsque vos valeurs de retour se révéleront être modifiables après tout.

91
Rob Kennedy

J'ai rencontré cet avertissement lors de la compilation de code qui utilise Boost.ProgramOptions. J'utilise -Werror donc l'avertissement tuait ma version, mais parce que la source de l'avertissement était dans les profondeurs de Boost, je ne pouvais pas m'en débarrasser en modifiant mon code.

Après beaucoup de recherches, j'ai trouvé l'option du compilateur qui désactive l'avertissement:

-Wno-ignored-qualifiers

J'espère que cela t'aides.

19
ccaughie

Le renvoi d'une valeur constante n'a de sens que lorsque vous renvoyez une référence ou un pointeur (dans ce cas, le pointeur vers constant et non un pointeur constant) car l'appelant est en mesure de modifier la valeur référencée (pointée vers).

Un autre commentaire sur le code sans rapport avec votre question: je pense qu'il vaut mieux utiliser un setter au lieu de

int& getNonconstReference() {
    return _myInt;
}

Ce qui devrait être:

void setMyInt(int n) {
  _myInt = n;
}

De plus, il est inutile de renvoyer une référence const à un int. Cela a du sens pour un objet plus grand dont la copie ou le déplacement est plus cher.

4
Brahim

Ayant cela

struct Foo { Foo(int) {} operator bool() { return true; } };

et cela

Foo some_calculation(int a, int b) { Foo result(a + b); /*...*/ return result; }

l'exemple

if (some_calculation(3, 20) = 40) { /*...*/ }

compile sans avertissement. Bien sûr, c'est rare. Mais n'est-il pas exact de faire en sorte qu'il soit difficile pour les gens de mal faire les choses? Et avec l'espoir que les gens essaient des choses qui sont mauvaises, le type de retour doit être déclaré const. Et: g ++ met en garde contre l'ignorance du classificateur, mais ne l'ignore pas. Je pense que l'avertissement concerne les utilisateurs qui prennent la copie et ignorent les classificateurs const sur leur copie. Mais cela ne devrait pas être un avertissement, car c'est un comportement absolument correct. Et cela a du sens de le faire.

2
mcbulba

-Pedantic ne devrait-il pas permettre une stricte adhésion à la norme ISO? En fonction de -std = bien sûr ...

1
Steve

Cet avertissement est également utile pour éviter toute confusion lors de la déclaration de fonctions renvoyant des pointeurs vers des objets qui ne doivent pas être modifiés:

// "warning: type qualifiers ignored on function return type"
// as the pointer is copied. 
Foo* const bar();

// correct:
const Foo* bar();
1
Luchs

Il y a une différence entre const sur un résultat de type basique, où il est ignoré, et const sur un résultat de type classe, où il fait généralement des ravages.

namespace i {
    auto f() -> int const { return 42; }
    void g( int&& ) {}
}

namespace s {
    struct S {};
    auto f() -> S const { return {}; }
    auto g( S&&  ) {}
}

auto main() -> int
{
    { using namespace i; g( f() ); }    // OK
    { using namespace s; g( f() ); }    // !The `const` prevents this.
}

C'est pourquoi le compilateur met en garde dans le premier cas: c'est un cas particulier, qui peut ne pas faire ce à quoi on pourrait s'attendre naïvement.

Pour la programmation moderne, à mon humble avis, Nice serait également avec un avertissement concernant const sur le résultat du type de classe, car il interdit le déplacement de la sémantique; un coût assez élevé pour le peu d'avantages que l'on envisageait.

0