enum vs constexpr für tatsächliche statische Konstanten innerhalb von Klassen

Lassen Sie mich mit meiner Absicht beginnen. In den alten (C ++) Tagen hätten wir Code wie:

class C
{
public:
  enum {SOME_VALUE=27};
};

Dann könnten wir verwendenSOME_VALUE in unserem Code als Kompilierzeitkonstante und überall dort, wo der Compiler sehen würdeC::SOME_VALUEwürde es nur das wörtliche 27 einfügen.

Heutzutage scheint es akzeptabler zu sein, diesen Code in so etwas wie:

class C
{
public:
  static constexpr int SOME_VALUE=27;
};

Das sieht viel sauberer aus, gibtSOME_VALUE Ein klar definierter Typ, der ab C ++ 11 der bevorzugte Ansatz zu sein scheint. Das (zumindest für mich unvorhergesehene) Problem ist, dass dies auch Szenarien verursacht, in denenSOME_VALUE muss extern gemacht werden. Das heißt, in irgendeiner cpp-Datei müssen wir Folgendes hinzufügen:

constexpr int C::SOME_VALUE; // Now C::SOME_VALUE has external linkage

Die Fälle, die dies verursachen, scheinen zu sein, wenn const auf verweistSOME_VALUE werden verwendet, was im C ++ Standard Library-Code recht häufig vorkommt (siehe Beispiel am Ende dieser Frage). Ich benutze übrigens gcc 4.7.2 als meinen Compiler.

Aufgrund dieses Dilemmas bin ich gezwungen, zur Definition zurückzukehrenSOME_VALUE als Aufzählung (d. h. alte Schule), um zu vermeiden, dass für einige, aber nicht für alle meiner statischen constexpr-Mitgliedsvariablen eine Definition zu einer cpp-Datei hinzugefügt werden muss. Gibt es nicht eine Möglichkeit, dem Compiler das mitzuteilen?constexpr int SOME_VALUE=27 bedeutet, dassSOME_VALUE sollte ... behandelt werdennur als Kompilierzeitkonstante und niemals als Objekt mit externer Verknüpfung? Wenn Sie eine damit verwendete const-Referenz sehen, erstellen Sie eine temporäre. Wenn Sie sehen, dass die Adresse vergeben ist, erzeugen Sie einen Kompilierungsfehler, falls dies erforderlich ist. B, da es sich um eine Kompilierungszeitkonstante handelt und nicht mehr.

Hier ist ein anscheinend harmloser Beispielcode, für den wir die Definition hinzufügen müssenSOME_VALUE in einer cpp-Datei (erneut getestet mit gcc 4.7.2):

#include <vector>

class C
{
public:
  static constexpr int SOME_VALUE=5;
};

int main()
{
  std::vector<int> iv;

  iv.push_back(C::SOME_VALUE); // Will cause an undefined reference error
                               // at link time, because the compiler isn't smart
                               // enough to treat C::SOME_VALUE as the literal 5
                               // even though it's obvious at compile time
}

Durch Hinzufügen der folgenden Zeile zum Code im Dateibereich wird der Fehler behoben:

constexpr int C::SOME_VALUE;

Antworten auf die Frage(6)

Ihre Antwort auf die Frage