boost::lexical_cast + enum + unnamed namespace



  • Hallo Leute,

    ich habe einen komischen Effekt bei der Ausgabe eines enums in einen (i)ostream. Das Verhalten von lexical_cast verändert sich, wenn ich die Ausgabefunktion für den enum in einen unnamed namesapce stecke.

    Das ist der Code:

    #include <iostream>
    #include <sstream>
    #include <boost/lexical_cast.hpp>
    
    class Foo
    {
    public:
        enum Side { top, bottom };
        explicit Foo( Side side ) : m_side( side ) {}
        Side m_side;
    };
    
    namespace // unnamed namespace!
    {
        std::ostream& operator<<( std::ostream& out, Foo::Side side )
        {
            return out << (side == Foo::top? "top": "bottom");
        }
    }
    
    int main()
    {
        using namespace std;
        Foo f( Foo::bottom );
        cout << "Side: " << f.m_side << endl;
    
        stringstream buf;
        buf << "Side: " << f.m_side;
        cout << "stringstream [" << buf.str() << "]" << endl;
    
        cout << "lexical_cast [" << ("Side: " + boost::lexical_cast< std::string >( f.m_side )) << "]" << endl;
        return 0;
    }
    

    und das ist die (unerwartete) Ausgabe:

    Side: bottom
    stringstream [Side: bottom]
    lexical_cast [Side: 1]
    

    d.h. der lexical_cast behandelt den enum wie einen int.

    Lasse ich aber den unnamend namespace weg, so erhalte ich wie gewünscht:

    Side: bottom
    stringstream [Side: bottom]
    lexical_cast [Side: bottom]
    

    Ich habe das debuggt und gesehen, dass innerhalb des lexical_cast auch nur ein iostream verwendet wird, genau wie der sstream. Das sollte also keinen Unterschied machen.

    Hat irgend jemand eine Erklärung?
    Ich verwende VC8 und boost-1.38

    Gruß
    Werner



  • Push: .. kein Experte online?



  • Werner Salomon schrieb:

    Push: .. kein Experte online?

    Dein operator<< im anonymen, lokalen Namensraum der Übersetzungseinheit ist auch nur in dieser bekannt. Beim std::basic_stringstream<...> in den Interna von boost::lexical_cast ist die Funktion daher nicht sichtbar. Der Compiler wählt hier daher den nächstbesten Typen (int). Für die Version ohne Namespace ist das hingegen nicht der Fall.

    Edit: Man, ich sollte mal einen Deutschkurs an der VHS besuchen. 🙄



  • Ev. hilft das weiter:
    http://www.cprogramming.com/tutorial/namespaces.html
    (Abschnitt über den anonymen Namespace.)

    Simon



  • Tachyon schrieb:

    Dein operator<< im anonymen, lokalen Namensraum der Übersetzungseinheit ist auch nur in dieser bekannt.

    Danke für die Antwort.
    Ich war bisher der Meinung, das alles was inkludiert wird, mit zu der Übersetzungseinheit dazu gehört - ist das nicht so?

    Gruß
    Werner



  • theta schrieb:

    Ev. hilft das weiter:
    http://www.cprogramming.com/tutorial/namespaces.html
    (Abschnitt über den anonymen Namespace.)

    Danke Simon,

    stimmt; da steht explizit, dass der unnnamed namespace nur innerhalb der Datei Gültigkeit hat. Wieder was dazu gelernt.

    Gruß
    Werner



  • Werner Salomon schrieb:

    theta schrieb:

    Ev. hilft das weiter:
    http://www.cprogramming.com/tutorial/namespaces.html
    (Abschnitt über den anonymen Namespace.)

    .. da steht explizit, dass der unnnamed namespace nur innerhalb der Datei Gültigkeit hat.

    Und das scheint schlicht falsch zu sein!
    Laut Stroustrup Kapitel 9 "Source Files and Programs" gehören alle #includes und aufgelösten Makros mit zu der Übersetzungseinheit (translation unit).
    Dafür spricht auch, dass ein selbst gestrickter lexical_cast - in der einfachsten denkbaren Fassung - den Streaming-Operator im unnamed namespace findet.

    Es scheint vielmehr ein Problem mit der Reihenfolge innerhalb der Übersetzungseinheit zu sein. Aber erklären kann ich es mir nach wie vor nicht.

    Gruß
    Werner


Anmelden zum Antworten