Probleme mit ostream& operator<<(ostream& ... )



  • Hi! :p

    struct B
    {
    };
    
    struct A
    {
    	B operator+(A) {return B();}
    };
    
    std::ostream& operator<<(ostream& stream, B& b) { stream << "B!!" << endl; return stream; }
    
    int main()
    {	
    	//~ cout << (A() + A()) << endl; // Geht nicht
    	B b = A() + A();
    	cout << b << endl;
    };
    

    Was muss ich machen damit das nicht kommt:

    g++ schrieb:

    Fehler: no match für »operator<<« in »std::cout << A().A::operator+((A(), A()))«

    template<typename T>
    class A
    {
    	T i;
    
    	friend ostream& operator<< <>(ostream&, A<T>&);
    };
    
    template<typename T>
    ostream& operator<<(ostream& s, A<T>& a)
    { 
    	s << a.i; 
    	return s; 
    }
    
    int main()
    {
        A<int> a;
        cout << a << endl;
    }
    

    bekomm ich auch nicht zum laufen ... 😕 😕 😞



  • Pigeon schrieb:

    struct B
    {
    };
    
    struct A
    {
    	B operator+(A) {return B();}
    };
    
    std::ostream& operator<<(ostream& stream, B& b) { stream << "B!!" << endl; return stream; }
    
    int main()
    {	
    	//~ cout << (A() + A()) << endl; // Geht nicht
    	B b = A() + A();
    	cout << b << endl;
    };
    

    Was muss ich machen damit das nicht kommt:

    g++ schrieb:

    Fehler: no match für »operator<<« in »std::cout << A().A::operator+((A(), A()))«

    nun zum einen fehlt das '#include <iostream>', dann einige vorangestellte std:: und const - folgendes compiliert:

    #include <iostream>
    
    struct B
    {
    };
    
    struct A
    {
        B operator+(A) const {return B();}
    };
    
    std::ostream& operator<<( std::ostream& stream, const B& b)  // std:: vor ostream
    {
        stream << "B!!" << std::endl;   // std:: vor endl
        return stream;
    }
    
    int main()
    {  
        using namespace std; // ersetzt das std:: vor cout und endl weiter unten
        cout << (A() + A()) << endl; // Geht schon
        B b = A() + A();
        cout << b << endl;
    }
    

    Pigeon schrieb:

    template<typename T>
    class A
    {
    	T i;
    
    	friend ostream& operator<< <>(ostream&, A<T>&);
    };
    
    template<typename T>
    ostream& operator<<(ostream& s, A<T>& a)
    { 
    	s << a.i; 
    	return s; 
    }
    
    int main()
    {
        A<int> a;
        cout << a << endl;
    }
    

    bekomm ich auch nicht zum laufen ... 😕 😕 😞

    So funktioniert's:

    #include <iostream>
    
    template<typename T>
    class A
    {
        T i;
    
        friend std::ostream& operator<<( std::ostream& s, A& a )
        { 
            s << a.i; 
            return s; 
        }
    };
    
    int main()
    {
        using namespace std;
        A<int> a;
        cout << a << endl;
    }
    

    .. wobei ich nicht wirklich weiß, wie man den Body der Template-Ausgabe-Funktion nicht inline macht 😕

    Gruß
    Werner



  • Danke 🤡
    Ja iostream und using namespace std hatte ich natürlich.

    Warum muss denn ein const in den operator?? Und welche Auswirkung hat das auf die Referenz???? 😕 😕 😮


  • Mod

    Werner Salomon schrieb:

    .. wobei ich nicht wirklich weiß, wie man den Body der Template-Ausgabe-Funktion nicht inline macht 😕

    Es handelt sich nicht um eine einzelne Funktion aber auch nicht um ein Funktionstemplate oder ein Member eines Templates - damit scheidet eine Templatedefinition um diese Funktionen zu definieren aus. Andererseits hängen diese natürlich irgendwie von den Templateparametern der Klasse ab - und so etwas kann nur durch Templatedefinitionen beschrieben werden. Schlussfolgerung: es ist nicht möglich, alle diese Funktionen außerhalb des Klassentemplates zu definieren.
    Möglich ist lediglich die Definition einzelner Funktionen jeweils für ein bestimmtes Templateargumenttupel - hier besteht dann keine Abhängigkeit von irgendwelchen Parametern mehr und eine ganz normale Funktionsdefinition erfüllt diesen Zweck.



  • Pigeon schrieb:

    Warum muss denn ein const in den operator?? Und welche Auswirkung hat das auf die Referenz???? 😕 😕 😮

    Also es muss auf jeden Fall beim Streaming-operator ein const vor die Referenz, wenn Du den Ausdruck

    cout << (A() + A())
    

    übersetzen willst.

    Das Resultat von (A() + A()) ist ein temporäres Objekt vom Typ B und dieses darfst Du nicht an eine Funktion - in diesem Fall 'operator<<( std::ostream&, B& )' übergeben. Das geht nur per const referenz oder per Value.

    Gruß
    Werner



  • @camper Danke für die Antwort - hört sich ja etwas verwirrend an 'keine Funktion' aber auch 'kein Funktionstemplate' ..

    Kann man die Konstruktion auch so aufbauen

    #include <iostream>
    
    template<typename T>
    class A
    {
        T i;
    
        template< typename U >
        friend std::ostream& operator<<( std::ostream& s, A< U >& a );
    };
    template< typename U >
    std::ostream& operator<<( std::ostream& s, A< U >& a );
    {
        s << a.i;
        return s;
    }
    

    mir ist klar, dass das nicht dasselbe ist - mich würde nur mal interessieren wie das korrekt aussehen muss. Die Kombination friend plus template frisst kein Compiler. Der operator<< sollte doch jetzt nicht mehr von T abhängig sein, oder sehe ich das falsch?

    Gruß
    Werner


Log in to reply