web-dev-qa-db-fra.com

Membre const non statique, impossible d'utiliser l'opérateur d'affectation par défaut

Un programme que j'étends utilise std::pair<> beaucoup.

Il y a un point dans mon code où le compilateur lance un assez gros:

Le membre const non statique, 'const Ptr std :: pair, const double *> :: first' ne peut pas utiliser l'opérateur d'affectation par défaut

Je ne sais pas vraiment à quoi cela fait référence? Quelles méthodes manquent dans la classe Ptr?

L'appel d'origine qui provoque ce problème est le suivant:

vector_of_connections.pushback(pair(Ptr<double,double>,WeightValue*));

Où ça met un std::Pair<Ptr<double,double>, WeightValue*> sur un vecteur, où WeightValue* est une variable const d'environ 3 fonctions en arrière, et le Ptr<double,double> provient d'un itérateur qui fonctionne sur un autre vecteur.

Pour référence future, Ptr<double,double> est un pointeur vers un objet Node.

44
Ed James

Vous avez un cas comme celui-ci:

struct sample {
    int const a; // const!

    sample(int a):a(a) { }
};

Maintenant, vous l'utilisez dans un contexte qui nécessite que sample soit assignable - possible dans un conteneur (comme une carte, un vecteur ou autre chose). Cela échouera, car l'opérateur d'affectation de copie défini implicitement fait quelque chose dans ce sens:

// pseudo code, for illustration
a = other.a;

Mais a est const !. Vous devez le rendre non constant. Cela ne fait pas de mal car tant que vous ne le modifiez pas, il reste logiquement constant :) Vous pouvez résoudre le problème en introduisant un operator= aussi, ce qui oblige le compilateur à ne pas en définir un implicitement. Mais c'est mauvais car vous ne pourrez pas changer votre membre const. Ainsi, avoir un opérateur =, mais toujours pas assignable! (car la copie et la valeur assignée ne sont pas identiques!):

struct sample {
    int const a; // const!

    sample(int a):a(a) { }

    // bad!
    sample & operator=(sample const&) { }
};

Cependant dans votre cas, le problème apparent se situe apparemment dans std::pair<A, B>. N'oubliez pas qu'un std::map est trié sur les clés qu'il contient. Pour cette raison, vous ne pouvez pas changer ses clés, car cela pourrait facilement rendre l'état d'une carte invalide. Pour cette raison, ce qui suit tient:

typedef std::map<A, B> map;
map::value_type <=> std::pair<A const, B>

Autrement dit, il interdit de changer ses clés qu'il contient! Donc si tu le fais

*mymap.begin() = make_pair(anotherKey, anotherValue);

La carte vous envoie une erreur, car dans la paire de valeurs stockées dans la carte, le ::first le membre a un type qualifié const!

77

J'ai rencontré le même problème et suis tombé sur cette page.

http://blog.copton.net/archives/2007/10/13/stdvector/index.html

Depuis la page:

Veuillez noter que ce n'est pas un problème spécifique GNU ici. La norme ISO C++ requiert que T ait un opérateur d'affectation (voir la section 23.2.4.3). Je viens de montrer sur l'exemple de l'implémentation STL de GNU où cela peut mener à.

14
user288157

Autant que je sache, quelque part vous avez quelque chose comme:

// for ease of reading 
typedef std::pair<const Ptr<double, double>, const double*> MyPair;

MyPair myPair = MAKEPAIR(.....);
myPair.first = .....;

Étant donné que les membres de MyPair sont const, vous ne pouvez pas leur affecter.

1
James Curran