2010-08-13 14 views
2

Dire que j'ai une classe « Code » défini comme celui-ci, avec une conversion de type défini par l'utilisateur type int:expression constante attendu échoue lamentablement dans l'instruction switch

class Code 
{ 
public:  
    int code; 
    std::string description; 

    Code (const int c, const std::string& d) : code(c), description(d) { ; } 

    operator int() const { return code; } 
}; 

Et une deuxième classe « Master » en utilisant la classe de code :

class Master 
{ 
public: 
    Code master_code; 
}; 

en plus d'un groupe de codes prédéfinis, comme ceci:

const Code CODE_ONE (1, "This is code one"); 
const Code CODE_TWO (2, "This is code two"); 
const Code CODE_THREE (3, "This is code three"); 

On penserait (c'est à dire. Je pense) que l'on pourrait l'utiliser comme ceci:

Master master_obj; 
switch (master_obj.master_code) 
{ 
    case CODE_ONE: 
     // ... 
     break; 

    case CODE_TWO: 
     // ... 
     break; 

    case CODE_THREE: 
     // ... 
     break; 

    default: 
     // ... 
} 

en raison de la conversion automatique de type int, mais ce ne semble pas être le cas. GCC me dit que CODE_ONE, CODE_TWO et CODE_THREE "ne peuvent pas apparaître dans une expression constante".

Cela ne fonctionne pas non plus, par la voie:

Master master_obj; 
switch (master_obj.master_code) 
{ 
    case CODE_ONE.code: 
     // ... 
     break; 

    case CODE_TWO.code: 
     // ... 
     break; 

    case CODE_THREE.code: 
     // ... 
     break; 

    default: 
     // ... 
} 

Les rendements ci-dessus exactement la même erreur: « 'CODE_ONE ne peuvent pas apparaître dans une expression constante » en plus d'un « ." ne peut pas apparaître dans une expression constante ".

Mais cela fonctionne:

Master master_obj; 
switch (master_obj.master_code) 
{ 
    case 1: 
     // ... 
     break; 

    case 2: 
     // ... 
     break; 

    case 3: 
     // ... 
     break; 

    default: 
     // ... 
} 

Alors CODE_ONE etc. ne peut pas être résolu comme des expressions constantes? Cela semble bizarre ... Ou est-ce que je fais quelque chose de mal?

Répondre

6

Les étiquettes dans une instruction switch doivent être des "expressions-constantes" (§6.4.2/2). Une expression constante intégrale » est définie comme (§5.19/1):

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used, and assignment, increment, decrement, function-call, or comma operators shall not be used.

Donc, vous ne pouvez pas avoir un appel de fonction (y compris une fonction de conversion), et un membre de données doit être statique (qui vôtre isn « t).

+0

Oh bum. Eh bien, merci de clarifier alors. – Oystein

+2

@oystein: Je devrais probablement ajouter que C++ 0x développe un peu l'idée des expressions constantes. Il ajoute 'constexpr', que vous pouvez utiliser pour marquer les choses comme des expressions constantes, donc avec quelque chose comme' int constexpr f() {return 1; } 'vous pouvez utiliser' f() 'comme une expression constante. –

0

étiquettes de cas d'une des déclarations de cas de commutation doit être compiler des constantes de temps et doit faire partie intégrante. CODE_ONE, CODE_TWO etc sont compile pas constantes de temps intégrales.

Référez-6.4.2/2

1

Les étiquettes de commutateur doivent être des constantes de compilation. comparer ne sont pas disponibles avant que les objets CODE_XXX aient été créés lors de l'exécution.

0

Le fait que CODE_ONE, ... etc soit défini comme const ne signifie pas qu'ils sont réellement des expressions constantes. Tout ce que const fait est 'essayer' et appliquer que ces instances de classe ne changent pas par des règles définies const. À la fin, une instance de classe (ou structure d'ailleurs) n'est jamais considérée comme une expression entièrement constante puisqu'il s'agit d'un objet dynamique. Ce dont une instruction switch a besoin est une "expression de la constante de compilation" qui, à toutes fins utiles, concernant C++ 98 est un int littéral ou une valeur enum (aussi int littéral à la fin).

C++0x' constexpr vous permettra de faire des choses plus complexes comme utiliser des fonctions constantes, mais pas ce que vous demandez.