Konstanten in Header-Datei (map<>)



  • Hallo zusammen,

    ich habe für mein Projekt viele physikalische Konstanten die ich in einer Headerdatei für alle Source-Files zur Verfügung stehen habe.

    Bei den Atomgewichten von Spezies habe ich eine Map verwendet:

    //- Constants and their weight [g/mol]
    map<string, scalar> AW      
    {
        { "H", 1.00790 },
        { "O", 15.9994 },
        { "C", 12.0110 },
        { "N", 14.0067 },
        { "AR", 39.9480 },
        { "HE", 4.00260 }
    };
    

    Problem hier ist jetzt, dass ich immer eine Redefinierung bekomme, sobald ich die Header in einer anderen Source einbinde. Mit constexpr oder const funktioniert es derzeit nicht und ich komm nicht drauf wie ich das in Griff bekomm.

    Habt ihr mir einen Ratschlag?
    Grüße Tobi



  • In der Header Datei nur die Deklaration, also map<string, scalar> AW;
    Definition (also tatsächlich jetzt im Speicher anlegen) dann in einer Source Datei.

    Kannst dir aber auch eine Funktion bauen, die dir das erledigt, dann hast du das Problem nicht mehr und du hast es ein bisschen mehr gekapselt.

    double getConstVal(const std::string& name){...}



  • phyconst schrieb:

    In der Header Datei nur die Deklaration, also map<string, scalar> AW;

    extern map<string, scalar>;



  • sebi707 schrieb:

    phyconst schrieb:

    In der Header Datei nur die Deklaration, also map<string, scalar> AW;

    extern map<string, scalar>;

    danke



  • Okay,... danke...

    Gleich noch ne Frage. Sollte ich meine anderen Konstanten auch mit extern oder constexpr definieren?



  • Andere einfache Konstanten mit Typ int oder float kann man mit constexpr oder const im Header definieren. Der wichtige Unterschied zu der extern Variante ist, dass dann jede *.cpp Datei seine eigene Variable kriegt. Bei ein paar ints mag das egal sein, eine große Map möchte man vielleicht nur einmal haben.

    PS: Eigentlich müsste deine Map zusammen mit const im Header auch funktionieren. Tut es zumindest bei mir. Was für einen Fehler kriegst du?


  • Mod

    Shor-ty schrieb:

    Okay,... danke...

    Gleich noch ne Frage. Sollte ich meine anderen Konstanten auch mit extern oder constexpr definieren?

    Kommt drauf an, was du erreichen möchtest. Momentan hat das, was du tust, nicht viel mit Konstanten zu tun. Es ist ein fetter Lookup in einer Map, der zur Laufzeit erfolgt.


  • Mod

    sebi707 schrieb:

    PS: Eigentlich müsste deine Map zusammen mit const im Header auch funktionieren. Tut es zumindest bei mir. Was für einen Fehler kriegst du?

    Müsste sie nicht. Klassischer Verstoß gegen die ODR. Streng genommen müssten nicht einmal Fließkommakonstanten funktionieren, nur für Ganzzahlen ist das explizit erlaubt.



  • Ach ich Idiot, es liegt gar nicht an der Header 🙂
    Danke für den Hinweis; komplett übersehen. Ich greife auf diese Map wie folgt zu:

    return AFC::Constants::AW[atom] * stod(multiplicator);
    

    Die Variable "atom" beinhaltet einen string.

    Wenn ich die map mit const definiere erhalte ich folgenden Fehler:

    thermo/thermoReader.cpp: In member function 'AFC::scalar AFC::ThermoReader::calcWeight(const word&, const string&, const word&)':
    thermo/thermoReader.cpp:174:30: error: no match for 'operator[]' (operand types are 'AFC::map<std::basic_string<char>, double> {aka const std::map<std::basic_string<char>, double, std::less<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, double> > >}' and 'const word {aka const std::basic_string<char>}')
         return AFC::Constants::AW[atom] * stod(multiplicator);
    

    Ich schau mal nochmals nach wie ich die map richtig aufrufe.


  • Mod

    Das kommt wiederum davon, dass man den Operator[] nicht auf konstante Map-Objekte anwenden kann, da er die Map potentiell verändern kann.



  • Okay danke, dass wusst ich auch noch nicht. Habs nun mit ".at()" gelöst.



  • Noch was vergessen.

    Die Map wird alle chemischen Elemente und deren Atomgewicht enthalten. Empfiehlst du dann die extern Variante oder const?

    WIrd in 2 - 4 Source Files verwendet. Denke die Map ist dann nicht all zu groß und ich kann auch die const-Methode verwenden.

    Danke,
    Tobi



  • SeppJ schrieb:

    sebi707 schrieb:

    PS: Eigentlich müsste deine Map zusammen mit const im Header auch funktionieren. Tut es zumindest bei mir. Was für einen Fehler kriegst du?

    Müsste sie nicht. Klassischer Verstoß gegen die ODR. Streng genommen müssten nicht einmal Fließkommakonstanten funktionieren, nur für Ganzzahlen ist das explizit erlaubt.

    Ist Zeug mit const nicht implizit static ? Wird zumindest mehrfach auf Stackoverflow behauptet. Ich find nur gerade kein Zitat aus dem C++ Standard.



  • sebi707 schrieb:

    SeppJ schrieb:

    sebi707 schrieb:

    PS: Eigentlich müsste deine Map zusammen mit const im Header auch funktionieren. Tut es zumindest bei mir. Was für einen Fehler kriegst du?

    Müsste sie nicht. Klassischer Verstoß gegen die ODR. Streng genommen müssten nicht einmal Fließkommakonstanten funktionieren, nur für Ganzzahlen ist das explizit erlaubt.

    Ist Zeug mit const nicht implizit static ? Wird zumindest mehrfach auf Stackoverflow behauptet. Ich find nur gerade kein Zitat aus dem C++ Standard.

    Heißt ich sollte also mit extern und Source + Header arbeiten? Definiere nämlich auch einige Double in der Header.



  • sebi707 schrieb:

    Ich find nur gerade kein Zitat aus dem C++ Standard.

    Gefunden:

    §3.5 Abs. 3 schrieb:

    A name having namespace scope (3.3.6) has internal linkage if it is the name of
    — a variable, function or function template that is explicitly declared static; or,
    a variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage; or
    — a data member of an anonymous union.


  • Mod

    sebi707 schrieb:

    sebi707 schrieb:

    Ich find nur gerade kein Zitat aus dem C++ Standard.

    Gefunden:

    §3.5 Abs. 3 schrieb:

    A name having namespace scope (3.3.6) has internal linkage if it is the name of
    — a variable, function or function template that is explicitly declared static; or,
    a variable of non-volatile const-qualified type that is neither explicitly declared extern nor previously declared to have external linkage; or
    — a data member of an anonymous union.

    Interessant. Dann müsste es eigentlich funktionieren.

    Shor-ty schrieb:

    Heißt ich sollte also mit extern und Source + Header arbeiten? Definiere nämlich auch einige Double in der Header.

    Wenn du mich fragen würdest, würde ich gar keine Map für diesen Zweck einsetzen. Du wünscht dir doch sicherlich echte Compilezeitkonstanten (wozu sonst der Aufwand?), was aber von der Map effektiv verhindert wird.



  • Wenn du mich fragen würdest, würde ich gar keine Map für diesen Zweck einsetzen. Du wünscht dir doch sicherlich echte Compilezeitkonstanten (wozu sonst der Aufwand?), was aber von der Map effektiv verhindert wird.

    Zu was würdest du denn raten?


  • Mod

    Shor-ty schrieb:

    Zu was würdest du denn raten?

    Ganz einfach ohne map:

    namespace AW
    {
      const double H = 1.00790;
      // ...
    }
    

Anmelden zum Antworten