outsput operator für enum?



  • Hallo zusammen,

    ich habe eine enum, welche einen Fehlerwert abbildet, welche ich über einen Output operator ausgeben will. In meiner Header-Datei ErrorState.h steht.

    enum ErrorState {
                    E_0,
                    E_1,
                    E_2
            };
    std::ostream& operator<<(std::ostream& out, const ErrorState & s){
        std::stringbuf buf;
                switch(s){
    
                    case E_0:
                    {
                        buf.str("E_0");
                        break;
                    }
                    case E_1:
                        buf.str("E_1");
                        break;
                    case E_2:
                        buf.str("E_2");
                        break;
                    default:
                        buf.str("UNKNOWN ERROR STATE");
                    }
    
                out<< buf.str();
                return out;
    }
    

    Leider scheint es so nicht zu gehen, der Compiler sagt:

    In function `...::operator<<(std::basic_ostream<char, std::char_traits<char> >&, ErrorState const&)':
    ErrorState.h:38: multiple definition of `ubeeme::moversight::operator<<(std::basic_ostream<char, std::char_traits<char> >&, ErrorState const&)'
    ...:ErrorState.h:38: first defined here
    

    Jemand einen Tip?

    Danke.



  • uwerothfeld schrieb:

    Jemand einen Tip?

    Jap: Du bindest den Header in 2 Übersetzungseinheiten ein. In beiden ÜEs ist dann eine Definition des op<< vorhanden. Der Linker (und nicht der Compiler) bemerkt das, wenn er die ÜEs dann zusammenlinken will.

    Lösung:

    1. Deklariere den op<< im Header und definiere ihn in einer .cpp
      oder 2) Deklariere ihn als inline.

    Variante 1 ist häufig vorzuziehen, um Compilezeit-Abhängigkeiten zu vermindern.



  • Hmm...es ist schon richtig was pumuckl sagt, und es wird vermutlich später weitere Probleme auslösen, aber die Fehlermeldung sieht mir nach einem Compilerfehler aus. Wenn es der Linker wäre, würde er sich über zwei verschiedene .o-Dateien beschweren, nicht über die selbe .h-Datei.

    Für mich sieht es so aus, als fehlten dem Header die Include-Guards und werde er an zwei Stellen in der selben Übersetzungseinheit eingebunden. Schreib um den Inhalt des Headers etwas wie

    #ifndef INCLUDED_ERRORSTATE_H
    #define INCLUDED_ERRORSTATE_H
    
    //      ^-- Include-Guard
    
    enum ErrorState {
                    E_0,
                    E_1,
                    E_2
            };
    
    std::ostream& operator<<(std::ostream& out, const ErrorState & s);
    
    #endif
    

    und dann definier den operator<<, wie pumuckl sagt, in einer eigenen Quellcodedatei. Dass sollte sowohl diesen als auch den abzusehenden Linkerfehler beseitigen.



  • seldon schrieb:

    die Fehlermeldung sieht mir nach einem Compilerfehler aus. Wenn es der Linker wäre, würde er sich über zwei verschiedene .o-Dateien beschweren, nicht über die selbe .h-Datei.

    Für mich sieht es so aus, als fehlten dem Header die Include-Guards und werde er an zwei Stellen in der selben Übersetzungseinheit eingebunden.

    Nein, es ist tatsächlich ein Linkerfehler, iirc sagt der gcc das so mit multiple definition. In den Objektdateien steht drin, aus welchen Originaldateien die jeweiligen Definitionen stammen.

    Andernfalls hieße es wie folgt:

    prog.cpp: In function ‘int foo()’:
    prog.cpp:4: error: redefinition of ‘int foo()’
    prog.cpp:1: error: ‘int foo()’ previously defined here
    

Anmelden zum Antworten