2016-04-16 21 views
2

Um es kurz zu machen, hier ist ein minimales Beispiel:C++ Fehler: 'x' ist kein konstanter Ausdruck, wie zu beheben?

struct C { 
    const int X = 2; 
    int y = 2; 
}; 
void f(C* x) { 
    switch(x->y) { 
     case x->X: printf("%d", 42); break; 
     case 123: printf("foo"); 
    } 
} 
int main() 
{ 
    C c; 
    f(&c); 
    return 0; 
} 

Warum ist der Compiler error: 'x' is not a constant expression und wie beschweren, es zu beheben?

+0

Versuchen Sie, C :: X als statischen consExpr zu deklarieren. Und dann benutze C :: X in dem Fall anstelle von x-> X – DarthRubik

+0

Sie können nicht 'x-> X' als Fall für den Schalter verwenden. – Nacho

+0

@DarthRubik Ich möchte keine statischen Variablen, wenn es nicht wirklich notwendig ist. – mak

Antwort

6

Fall Etiketten innerhalb switch akzeptieren nur Kompilierungszeit konstante Ausdrücke. x->X ist nicht ein konstanter Ausdruck; daher könnte es nicht als ein case Etikett verwendet werden.

Ersetzen Sie die switch Anweisung mit einem if dieses Problem zu beheben:

if (x->y == x->X) { 
    printf("%d", 42); 
} else if (x->y == 123) { 
    printf("foo"); 
} 
0

In Haupt Sie eine Instanz von C deklarieren und zu f passieren. Gemäß der Definition von f garantiert es nicht, dass c nicht verändert wird - und main hat keine Möglichkeit, es zu verifizieren. Ich denke, f f(C * const x);

+0

Das hat nicht funktioniert – DarthRubik

0

Der angegebene Code (Modulo Formatierung)

struct C 
{ 
    int const x = 2; 
    int y = 2; 
}; 

& hellip sein muss; bedeutet dies:

struct C 
{ 
    int const x; 
    int y; 

    C(): x(2), y(2) {} 
}; 

& hellip; d.h. die Mitglieder werden von jedem Konstruktor initialisiert.

Sie können sogar, dass die Initialisierung in einem benutzerdefinierten Konstruktor überschreiben:

struct S 
{ 
    int const x = 2; 

    S(): x(3) {} 
}; 

Hier in jedem Fall x 3.

sein wird und so x ist keine Kompilierung konstant. Es ist sehr viel eine Laufzeitsache. Und als solches kann es nicht als case Label in einem switch verwendet werden, weil ein case Label ein Wert sein muss, der zur Kompilierzeit bekannt ist. Da das switch-Konstrukt dafür entworfen wurde, effizient als einfache Array-Indizierung (ein berechneter Sprung) implementiert zu werden, wenn der Wertebereich dies zulässt.


Eine einfache Lösung besteht darin, den relevanten Wert als Kompilierzeitkonstante zu definieren. Entweder als static oder enum Wert innerhalb der Klasse. Oder außerhalb der Klasse.


Eine weitere mögliche Lösung ist es, einen if zu verwenden - else Leiter anstelle ein switch.

0

Case akzeptiert Constant Expression, wie 2 oder "a". Und Const definieren nur eine unveränderliche Variante.