web-dev-qa-db-fra.com

Erreur: opérandes non valides des types ‘const char [35]’ et ‘const char [2]’ en binaire ‘opérateur +’

Au sommet de mon dossier, j'ai

#define AGE "42"

Plus tard dans le fichier, j'utilise plusieurs fois l'identifiant, y compris des lignes qui ressemblent à

1 std::string name = "Obama";
2 std::string str = "Hello " + name + " you are " + AGE + " years old!";
3 str += "Do you feel " + AGE + " years old?";

Je reçois l'erreur:

"erreur: opérandes non valides des types‘ const char [35] ’et‘ const char [2] ’en binaire‘ opérateur + '' "

ligne 3. J'ai effectué des recherches et découvert que c'était à cause de la façon dont C++ traitait les différentes chaînes et que je pouvais le réparer en remplaçant "AGE" par "string (AGE)". Cependant, j'ai raté accidentellement l'une des instances jusqu'à aujourd'hui et je me demandais pourquoi le compilateur ne se plaignait pas alors que j'avais toujours une instance où il s'agissait simplement de "AGE".

Après quelques essais et erreurs, j'ai constaté que je n'avais besoin que de string(AGE) sur des lignes où je ne concaténais pas une autre chaîne créée dans le corps de la fonction.

Ma question est la suivante: "Qu'est-ce qui se passe à l'arrière-plan que C++ n'aime pas concaténer une chaîne avec une chaîne placée par le pré-processeur, à moins que vous ne concaténiez également la chaîne que vous avez définie dans la fonction".

48
janovak

Considère ceci:

std::string str = "Hello " + "world"; // bad!

Les rhs et les lhs pour operator + Sont char* S. Il n’existe pas de définition de operator + Prenant deux char* (En fait, le langage ne vous autorise pas à en écrire un). En conséquence, sur mon compilateur, cela produit une erreur "ne peut pas ajouter deux pointeurs" (le vôtre énonce apparemment des choses en termes de tableaux, mais c'est le même problème).

Considérons maintenant ceci:

std::string str = "Hello " + std::string("world"); // ok

is une définition de operator + Qui prend un const char* Comme lhs et un std::string Comme rhs, alors tout le monde est heureux.

Vous pouvez étendre cela à une chaîne de concaténation aussi longue que vous le souhaitez. Cela peut devenir désordonné, cependant. Par exemple:

std::string str = "Hello " + "there " + std::string("world"); // no good!

Cela ne fonctionne pas car vous essayez de + Deux char* Avant que le lhs ait été converti en std::string. Mais c'est bien:

std::string str = std::string("Hello ") + "there " + "world"; // ok

Parce qu'une fois que vous avez converti en std::string, Vous pouvez + Autant de char* Supplémentaires que vous le souhaitez.

Si cela reste déroutant, il peut être utile d’ajouter des crochets pour mettre en évidence les règles d’associativité, puis de remplacer les noms de variables par leurs types:

((std::string("Hello ") + "there ") + "world");
((string + char*) + char*)

La première étape consiste à appeler string operator+(string, char*), définie dans la bibliothèque standard. Remplacer ces deux opérandes par leur résultat donne:

((string) + char*)

Ce qui est exactement ce que nous venons de faire et qui est toujours légal. Mais essayez la même chose avec:

((char* + char*) + string)

Et vous êtes bloqué, car la première opération tente d’ajouter deux char*.

Morale de l'histoire: si vous voulez vous assurer qu'une chaîne de concaténation fonctionnera, assurez-vous simplement que l'un des deux premiers arguments est explicitement de type std::string.

79
dlf

AGE est défini comme "42" donc la ligne:

str += "Do you feel " + AGE + " years old?";

est converti en:

str += "Do you feel " + "42" + " years old?";

Ce qui n'est pas valable depuis "Do you feel " et "42" sont tous deux const char[]. Pour résoudre ce problème, vous pouvez en faire un std::string ou simplement enlever le +:

// 1.
str += std::string("Do you feel ") + AGE + " years old?";

// 2.
str += "Do you feel " AGE " years old?";
10
clcto

À la ligne 2, il y a un std::string impliqué (name). Il y a des opérations définies pour char[] + std::string, std::string + char[], etc. "Hello " + name donne un std::string, qui est ajouté à " you are ", donnant une autre chaîne, etc.

En ligne 3, vous dites

char[] + char[] + char[]

et vous ne pouvez pas simplement ajouter des tableaux les uns aux autres.

4
Paul Roub

Vous ne pouvez pas concaténer des chaînes brutes comme celle-ci. operator+ ne fonctionne qu'avec deux std::string objets ou avec un std::string et une chaîne brute (de chaque côté de l'opération).

std::string s("...");
s + s; // OK
s + "x"; // OK
"x" + s; // OK
"x" + "x" // error

La solution la plus simple consiste à transformer votre chaîne brute en un fichier std::string première:

"Do you feel " + std::string(AGE) + " years old?";

Bien sûr, vous ne devriez pas utiliser une macro en premier lieu. C++ n'est pas C. Utilisez const ou, en C++ 11 avec le support du compilateur approprié, constexpr.

4
Christian Hackl

Dans ce cas particulier, une solution encore plus simple consisterait simplement à supprimer le "+" tous ensemble, car AGE est un littéral de chaîne et que ce qui vient avant et après est également un littéral de chaîne. Vous pouvez écrire la ligne 3 comme:

str += "Do you feel " AGE " years old?";

En effet, la plupart des compilateurs C/C++ concaténent automatiquement les littéraux de chaîne. Ce qui précède est équivalent à:

str += "Do you feel " "42" " years old?";

que le compilateur convertira en:

str += "Do you feel 42 years old?";

1
djulien

J'ai eu le même problème dans mon code. Je concaténais une chaîne pour créer une chaîne. Ci-dessous la partie de code.

int scannerId = 1;
std:strring testValue;
strInXml = std::string(std::string("<inArgs>" \
                        "<scannerID>" + scannerId) + std::string("</scannerID>" \
                        "<cmdArgs>" \
                        "<arg-string>" + testValue) + "</arg-string>" \
                        "<arg-bool>FALSE</arg-bool>" \
                        "<arg-bool>FALSE</arg-bool>" \
                        "</cmdArgs>"\
                        "</inArgs>");
0
Dig The Code