negativer static const führt zu undefined reference

Du bist neu in der Welt von C++? Dann schau hier herein!
Antworten
Spinoza
Beiträge: 23
Registriert: 4. März 2011 01:07

negativer static const führt zu undefined reference

Beitrag von Spinoza »

Hallo zusammen,
entschuldigt, dass ich in so kurzer Zeit noch eine Frage habe:

Code: Alles auswählen

class A
{
  public:
  static const double d = 1;
};

int main()
{
  double d = -A::d;
}
führt in der main funktion zu
/tmp/ccHqD7OY.o: In function `main':
t.cpp:(.text+0xb): undefined reference to `A::d'
collect2: ld returned 1 exit status
was ich mir nun wirklich nicht erklären kann. (Was mein ihr, wie lange es gedauert hat, diesen Fehler so zu isolieren!)
Nun das Absurdeste: Wenn ich das Minus vor A::d entferne und daraus ein "-1*" mache, stört's den linker nicht mehr.

Was geht hier in Stroustrups Kopf vor, was in Meinen nicht passen will?
Gruß,
Spinoza
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Re: negativer static const führt zu undefined reference

Beitrag von solarix »

Also bei mir lässt sich genau dieser Code problemlos übersetzen und ausführen...
Spinoza
Beiträge: 23
Registriert: 4. März 2011 01:07

Re: negativer static const führt zu undefined reference

Beitrag von Spinoza »

Crazy. Das muss ein Fehler im GCC 4.5.2 sein...
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: negativer static const führt zu undefined reference

Beitrag von franzf »

Ich weiß jetzt nicht genau wie das jetzt genannt wird, aber Deklaration+Definition in der Klassendefinition von static-Membern geht nur mit integralen Typen - double ist keiner. Du musst also Deklaration und Definition trennen. Definition einmal in einer .cpp-Datei.
Wenn es kompiliert ist es Zufall (oder eine wissentlich in Kauf genommene Nichtbeachtung des Standards ;))
Spinoza
Beiträge: 23
Registriert: 4. März 2011 01:07

Re: negativer static const führt zu undefined reference

Beitrag von Spinoza »

franzf hat geschrieben:Ich weiß jetzt nicht genau wie das jetzt genannt wird, aber Deklaration+Definition in der Klassendefinition von static-Membern geht nur mit integralen Typen - double ist keiner. Du musst also Deklaration und Definition trennen. Definition einmal in einer .cpp-Datei.
Wenn es kompiliert ist es Zufall (oder eine wissentlich in Kauf genommene Nichtbeachtung des Standards ;))
Tatsächlich. Wer kommt denn darauf, static int-definitionen zuzulassen aber doubles nicht. Stroustrup ist ein Narr... aber das war mir bereits bekannt.
Offensichtlich haben die Compilerbauer diese absurde Regel auch nicht so ganz raus.

Vielen Dank für die Aufklärung!
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: negativer static const führt zu undefined reference

Beitrag von franzf »

Spinoza hat geschrieben:Wer kommt denn darauf, static int-definitionen zuzulassen aber doubles nicht. Stroustrup ist ein Narr... aber das war mir bereits bekannt.
Das ist doch nicht Stroustrup allein! Hinter dem Standard sitzt ein risiges Kommitee, darunter auch "Abgesandte" der großen Compilerbauer, die auch ein Wörtchen mitzureden haben. Und die Leute wissen schon, was sie tun.
Der C++03 sagt explizit:
If a static data member is of const integral or const enumeration type, its declaration in the class
definition can specify a constant-initializer which shall be an integral constant expression (5.19).
Und jetzt ein Blick in den aktuellen C++-Standard (=C++11):
9.4.2:
3
If a static data member is of const literal type, its declaration in the class definition can specify a brace-or-
equal-initializer in which every initializer-clause that is an assignment-expression is a constant expression.
A static data member of literal type can be declared in the class definition with the constexpr specifier;
if so, its declaration shall specify a brace-or-equal-initializer in which every initializer-clause that is an
assignment-expression is a constant expression. [ Note: In both these cases, the member may appear in
constant expressions. — end note ] The member shall still be defined in a namespace scope if it is odr-
used (3.2) in the program and the namespace scope definition shall not contain an initializer.
§2.14 (Literals)
The type of a floating literal is double unless explicitly specified by a suffix. The suffixes f and F specify
float, the suffixes l and L specify long double. If the scaled value is not in the range of representable
values for its type, the program is ill-formed.
Das heißt, mit C++11 ist dein Programm absolut Standard-konform, mit C++03 leider nicht :(
Pass aber mit der odr (One definition rule) auf; ein "const double d;" in deiner .cpp sollte reichen.
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Re: negativer static const führt zu undefined reference

Beitrag von solarix »

Spannend, danke für die Auflösung! Zur Ergänzung: mein verwenderter Compiler ist gcc "4.4.3-4ubuntu5". Dass es bei mir klappt würde ich in diesem Fall eher als einen Fehler im 4.4.3er-Compiler interpretieren :wink:
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Re: negativer static const führt zu undefined reference

Beitrag von franzf »

solarix hat geschrieben:Spannend, danke für die Auflösung!
Bitte, macht mir ja Spaß ;)
Zur Ergänzung: mein verwenderter Compiler ist gcc "4.4.3-4ubuntu5". Dass es bei mir klappt würde ich in diesem Fall eher als einen Fehler im 4.4.3er-Compiler interpretieren :wink:
K.A... Im Standard steht "integrale Typen können bei der Deklaration initialisiert werden" und nicht explizit "alles andere ist verboten" - in wie weit der GCC da tatsächlich gegen den Standard verstößt oder nur eine weiche Formulierung ausnützt kann ich nicht sagen. Im Notfall ist alles, was nicht explizit im Stadard als erlaubt aufgeführt ist undefiniert ;)
Als einen Fehler würde ich aber definitiv das Verhalten beim OP betrachten - der Compiler meldet keinen Fehler, generiert aber keine ordentlichen Objectfiles, und erst der Linker erkennt das Problem. Vielleicht auf eine neuere 4.5er Version aktualisieren (4.5.3 bietet sich an :P) oder gleich zum 4.6er wechseln - da kanns aber mit manchen Paketen Probleme geben, weil mal wieder Header ausgemistet wurden.
Antworten