Manipulatoren für Länge der Ausgabe



  • Hallo,

    ich würde gerne Manipulatoren einführen, um komfortabel festlegen zu können, wie ausführlich Objekte benutzerdefinierter Klassen ausgegeben werden sollen. Also wenn ich ein Objekt a der Klasse A habe, möchte ich

    cout << short << a;
    

    oder

    cout << long << a;
    

    schreiben können.

    Kann man das irgendwie realisieren, ohne eine eigene Klasse, die ostream erweitert, definieren zu müssen?



  • Du könntest so nen Manipulator bauen:

    class A
    {
    private:
    // ...
    
    // friend für Templateklassen/Funktionen allgemein geht nicht, glaub ich
    };
    
    class manip<typename C>
    {
    private:
    const A& a_;
    public:
    A(const A& a) : a_(a) {}
    const A& getA() const {return A_;}
    };
    
    template<typename T>
    ostream& operator<<(ostream& os, const manip<T>& obj) {}
    
    // irgendwie spezialisieren
    ostream& operator<<(ostream& os, const manip<short>& obj)
    {
    os << obj.getA().getAttrib();
    return os;
    }
    

    Alles ungetestet. Aber wenn das klappt, ginge dann:

    std::cout << manip<short>(a) << manip<long>(a) << '\n';
    


  • ingobulla schrieb:

    Hallo,

    ich würde gerne Manipulatoren einführen, um komfortabel festlegen zu können, wie ausführlich Objekte benutzerdefinierter Klassen ausgegeben werden sollen. Also wenn ich ein Objekt a der Klasse A habe, möchte ich

    cout << short << a;
    

    oder

    cout << long << a;
    

    schreiben können.

    Kann man das irgendwie realisieren, ohne eine eigene Klasse, die ostream erweitert, definieren zu müssen?

    Ja. Du kannst Dir eigene Manipulatoren schreiben. Dafür musst Du ostream selbst nicht anfassen. Allerdings ist das kein ganz einfaches Thema, insbesonderes, wenn diese Parameter annehmen können sollen. Eine Suchmaschine hilft Dir weiter...

    Und hier gibts einen Artikel im Forum dazu.



  • Hallo ingobulla,

    so geht das:

    #include <iostream>
    
    struct Foo // irgendeine Klasse
    {
        Foo() : m_1(11), m_2(22), m_3(33) {}
        friend std::ostream& operator<<( std::ostream& out, const Foo& foo );
    private:
        int m_1, m_2, m_3; // irgendwelche Parameter
    };
    
    // --   global FOO_LENGTH-Index
    namespace
    {
        const int FOO_LENGTH = std::ios_base::xalloc();
    }
    
    // -- die Manipulatoren short_foo und long_foo setzen die 'Rucksackinformation'
    std::ostream& short_foo( std::ostream& out )
    {
        out.iword( FOO_LENGTH ) = 0;
        return out;
    }
    std::ostream& long_foo( std::ostream& out )
    {
        out.iword( FOO_LENGTH ) = 47;
        return out;
    }
    
    // --   Die Ausgabefunktion liest die 'Rucksackinformation' aus dem ostream
    std::ostream& operator<<( std::ostream& out, const Foo& foo )
    {
        out << foo.m_1; // die kurze Fassung
        if( out.iword( FOO_LENGTH ) > 0 ) // Bem.: falls kein Manipulator vorher gerufen wurde, so ist der Wert =0
        {
            out << "; " << foo.m_2 << "; " << foo.m_3;
        }
        return out;
    }
    
    int main()
    {
        using namespace std;
        Foo foo;
        cout << "kurz " << short_foo << foo << endl;
        cout << "lang " << long_foo << foo << endl;
        cout << "kurz " << short_foo << foo << endl;
        return 0;
    }
    

    Die Ausgabe hier wäre:

    kurz 11
    lang 11; 22; 33
    kurz 11
    

    Gruß
    Werner


Anmelden zum Antworten