add assign



  • hey

    ich habe eine kleine - noch unbeantwortete - frage. folgernder code gibt 12 aus:

    template<typename Derived>
    class MakeAddAssignable
    {
    protected:
    	MakeAddAssignable()
    	{
    	}
    public:
    	Derived& operator+= (Derived const& Rhs)
    	{
    		*static_cast<Derived*>(this) = *static_cast<Derived*>(this) + Rhs;
    		return *static_cast<Derived*>(this);
    	}
    };
    struct Foo : MakeAddAssignable<Foo>
    {
    	Foo(int d = 0)
    		: Data(d)
    	{
    	}
    	int Data;
    };
    Foo operator+ (Foo lhs, Foo rhs)
    {
    	return lhs.Data + rhs.Data;
    }
    #include <iostream>
    int main()
    {
    	Foo Data, b, c;
    	b.Data = 5;
    	c.Data = 7;
    	Data += b;
    	Data += c;
    	std::cout << Data.Data;
    	std::cin.get();
    }
    

    ist das - egal wie "Foo" in einem richtigen programm konkret aussieht - definiert und well-formed? ich habe eben angst so einfach einen base-pointer in einen derived-pointer zu casten und bin mir gerade nicht sicher wie das geregelt ist. wenn es nicht geht, wie sonst soll man das lösen?

    gruss

    ps.: ja, es ist mir bewusst dass man eigentlich den += operator mit dem + operator implementiert. das müsst ihr mir gar nicht sagen. nun ist es aber teilweise effizienter es andersherum zu machen....



  • -> CRTP


  • Mod

    #include <iostream>
    #include <type_traits>
    
    struct MakeAddAssignable {};
    
    template< typename T,
              typename = typename std::enable_if<std::is_base_of<MakeAddAssignable, T>::value>::type >
    T& operator+=( T& lhs, T const& rhs)
    {
    	lhs = lhs + rhs;
    	return lhs;
    }
    
    struct Foo : MakeAddAssignable
    {
    	Foo(int d = 0)
    		: Data(d) {}
    
    	int Data;
    };
    
    Foo operator+ (Foo lhs, Foo rhs)
    {
    	return lhs.Data + rhs.Data;
    }
    
    int main()
    {
        Foo Data, b, c;
        b.Data = 5;
        c.Data = 7;
        Data += b;
        Data += c;
        std::cout << Data.Data;
    }
    


  • vielen dank euch beiden, problem gelöst.



  • Den operator+= ueber den operator+ zu implementieren ist aber generell eine sehr dumme idee.



  • Shade Of Mine schrieb:

    Den operator+= ueber den operator+ zu implementieren ist aber generell eine sehr dumme idee.

    Jo, immer umgekehrt.



  • Shade Of Mine schrieb:

    Den operator+= ueber den operator+ zu implementieren ist aber generell eine sehr dumme idee.

    soll ich dafür unnötigen runtime overhead in kauf nehmen?



  • asfsdfa schrieb:

    Shade Of Mine schrieb:

    Den operator+= ueber den operator+ zu implementieren ist aber generell eine sehr dumme idee.

    soll ich dafür unnötigen runtime overhead in kauf nehmen?

    du verdrehst da was. die dumme idee ist die unperformante. operator+= braucht kein temporary, operator+ erzeugt immer eins.



  • otze schrieb:

    asfsdfa schrieb:

    Shade Of Mine schrieb:

    Den operator+= ueber den operator+ zu implementieren ist aber generell eine sehr dumme idee.

    soll ich dafür unnötigen runtime overhead in kauf nehmen?

    du verdrehst da was. die dumme idee ist die unperformante. operator+= braucht kein temporary, operator+ erzeugt immer eins.

    dass operator+= kein temporary braucht stimmt in gewissen fällen nicht. (bzw. es ist bei mir operator*=, aber alle beziehungen sind analog zu += und +).

    ➡

    otze schrieb:

    Es ist mir nicht klar, ob du matrix-produkt oder das elementweise-Produkt haben willst (beides wird je nach Sprache mit * notiert). adfasdfs gezeigter Code passt gut zum elementweisen produkt und wird so mit Sicherheit auch beim matrix-produkt funktionieren. Allerdings ist es beim echten Matrixprodukt besser wegen der Probleme mit der Matrixgröße sowie aliasing op = mithilfe von op zu implementieren, und nicht wie üblich umgekehrt. Das spart eine Kopie (du brauchst bei dem hier gezeigten Ansatz immer 2 temporäre Kopien bei Benutzung von op*)

    @Photon

    das wird heir ja gemacht. Nur nicht dein Code für a*b sondern a*=b und dann wird a*b mithilfe dieses operators implmentiert mittels:

    c=ab
    =>
    c=a;
    c
    =b;

    aus http://www.c-plusplus.net/forum/quote2367771



  • ja, aber das gilt für Matrizen, nicht für Foo.



  • otze schrieb:

    ja, aber das gilt für Matrizen, nicht für Foo.

    foo war nur ein beispiel für eine klasse, bei der die unübliche reihenfolge performanter ist. ich habe auch schon lange basisklassen geschrieben die operator$ anhand von operator$= implementieren, die ich auch für fast alles einsetze. aber für diesen ausnahmefall wie matrizen möchte ich auch basisklassen anbieten. ich hoffe, nun hab ich mich verstänlicher erklären können.


Anmelden zum Antworten