Question

Quelqu'un peut-il expliquer pourquoi le code suivant ne se compile pas (sur G ++ (GCC) 3.2.3 20030502 (Red Hat Linux 3.2.3-49))?

struct X {
public:
   enum State { A, B, C };

   X(State s) {}
};

int main()
{
   X(X::A);
}

Le message que je reçois est:

jjj.cpp: dans la fonction 'int main ()':
jjj.cpp: 10: 'xx :: a' n'est pas un membre statique de 'struct x'
jjj.cpp: 10: pas de fonction de correspondance pour l'appel à 'x :: x ()'
jjj.cpp: 1: les candidats sont: x :: x (const x &)
jjj.cpp: 5: x :: x (x :: état) `

Est-ce un mauvais code ou un bug du compilateur?

Problème résolu par Neil + Konrad. Voir les commentaires de la réponse de Neil ci-dessous.

Était-ce utile?

La solution

X(X::A);

est vu la déclaration de fonction ASA. Si vous voulez vraiment ce code, utilisez:

(X)(X::A);

Autres conseils

Vous avez oublié le nom de la variable dans votre définition:

int main()
{
   X my_x(X::A);
}

Votre code confond le compilateur car syntaxiquement il ne peut pas distinguer cela d'une déclaration de fonction (retour X et passant X::A comme argument). En cas de doute, le compilateur C ++ désambiguient toujours en faveur d'une déclaration.

La solution consiste à introduire des parenthèses redondantes autour du X Puisque le compilateur interdit les parenthèses autour des types (par opposition aux appels Constructo, etc.):

(X(X::A));

Juste pour le clarifier ce qui se passe. Regardez cet exemple

int main() {
    float a = 0;
    {
        int(a); // no-op?
        a = 1;
    }
    cout << a;
}

Que va-t-il sortir? Eh bien, il sortira 0. La int(a) de ci-dessus peut être analysé de deux manières différentes:

  • Lancer à int et rejeter le résultat
  • Déclarer une variable appelée a. Mais ignorez les parenthèses autour de l'identifiant.

Le compilateur, lorsqu'une telle situation apparaît où un plâtre de style fonction est utilisé dans une déclaration et qu'il ressemble également à une déclaration, le prendra toujours comme une déclaration. Lorsqu'il ne peut pas être syntaxiquement une déclaration (le compilateur examinera toute la ligne pour le déterminer), il sera considéré comme une expression. Ainsi nous attribuons à l'intérieur a Ci-dessus, en laissant l'extérieur a à zéro.

Maintenant, votre cas est exactement cela. Vous essayez (accidentellement) de déclarer un identifiant appelé A Au sein d'une classe appelée X:

X (X::A); // parsed as X X::A;

Le compilateur continue ensuite à gémir un constructeur par défaut non déclaré, car le statique, comme il le suppose, est construit par défaut. Mais même si vous aviez un constructeur par défaut pour X, il est bien sûr encore faux parce que ni l'un ni l'autre A est un membre statique de X, ni un statique de x ne peut être défini / déclaré à la portée du bloc.

Tu peux le faire ne pas ressemble à une déclaration en faisant plusieurs choses. Tout d'abord, vous pouvez parier toute l'expression, ce qui ne fait plus ressembler à une déclaration. Ou simplement paren le type qui est jeté. Ces deux désambigus ont été mentionnés dans d'autres réponses:

(X(X::A)); (X)(X::A)

Il y a une ambiguïté similaire mais distincte lorsque vous essayez de déclarer réellement un objet. Regardez cet exemple:

int main() {
    float a = 0;
    int b(int(a)); // object or function?
}

Car int(a) peut être à la fois la déclaration d'un paramètre appelé a et la conversion explicite (coulée) de la variable flottante en un INT, le compilateur décide à nouveau que c'est une déclaration. Ainsi, nous déclarons une fonction appelée b, qui prend un argument entier et renvoie un entier. Il existe plusieurs possibilités de désambiguïter cela, sur la base de la désambiguïsation de ci-dessus:

int b((int(a))); int b((int)a);

Vous devriez déclarer un objet comme

X x(X::A);

Bug dans votre code.

L'une ou l'autre de ces deux lignes fonctionne pour moi:

X obj(X::A);
X obj2 = X(X::A);

Comme le souligne Neil Butterworth, X(X::A) est traité comme une déclaration de fonction. Si vous voulez vraiment un objet anonyme, (X)(X::A) construire un objet X et le supprimer immédiatement.

Vous pourriez bien sûr faire quelque chose comme ça:

int main()
{
    // code
    {
    X temp(X::A);
    }
    // more code
}

Cela serait plus lisible et aurait essentiellement le même effet.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top