Implizite Konversion von zwei Klassen aus einer Library



  • Hallo,

    ich muss leider mit zwei verschiedenen Libraries arbeiten, welche eine unterschiedle Definition von Vektoren (im mathematischen Sinne) haben. Das führt leider aktuell dazu, dass ich häufig sowas schreiben muss:

    LibA::Vector3 vecA{vecB.x(), vecB.y(), vecB.z()};
    

    Das ist natürlich nicht optimal und ich möchte erreichen, dass ich sowas wie

    LabA::Vector3 vecA{vecB};
    

    schreiben kann. Mir ist bewusst, dass es dafür den operator() gibt, jedoch muss dieser ja innerhalb einer Klasse definiert werden, und da es sich im zwei Bibliotheken handelt, habe ich keinen Zugriff auf die Klassen.
    Wie kann ich also eine implizite Konversion von außerhalb erreichen?



  • Implizit geht es meines wissens nicht.

    entweder du schreibst schnell ein "vector_cast", was die c++-igste version wär.

    vecA = vector_cast <LibA::Vector3> (vecB);
    

    oder vllt:

    VectorA vector_cast(VectorB const& b) { /*...*/ }
    VectorB vector_cast(VectorA const& b) { /*...*/ }
    
    auto a = vector_cast(b);
    

    Oder wenn dir das zu lang ist, dann abuse ein Operator:

    class A
    {
    public:
        int x() const{}
        int y() const{}
        int z() const{}
    };
    class B
    {
    public:
        B() = default;
        B(int x, int y, int z){}
    };
    
    B& operator<<(B& left, A const& right)
    {
        left = B{right.x(), right.y(), right.z()};
        return left;
    }
    // und nochmal in andere richtigung von B nach A.
    
    int main()
    {
        A a;
        B b;
    
        b << a;
    }
    

    (Du solltest nur vorsichtig sein, dass der Operator nicht missverstanden werden kann, besonders nicht im mathematischen Sinne. Hier könnte man ja vielleicht eine Verschiebung vermuten, von b um a oder so, aber das musst du mit deinem Gewissen absprechen. - Bei längerem nachdenken würde ich sowas für math. Vektoren eher nicht machen)



  • Mir fällt nur eine "Näherungslösung" ein:

    LibA::Vector3 toAVec( const VecB& vecB)
    {
         return LibA::Vector3{vecB.x(), vecB.y(), vecB.z()};
    }
    
    auto vecA{ toAVec( vecB ) }:
    


  • Wenn beide Vektoren nur sagen wir mal drei Integer (x, y, z) beinhalten, diese in der gleichen Reihenfolge definiert sind (int x, y, z) und vom gleichen Typ kommen könntest du einfach einen schmutzigen C-Cast machen.



  • Vielen Dank für alle Vorschläge. Ich habe mich jetzt dafür entschieden einen vector_cast zu benutzen wie es 5script vorgeschlagen hat.



  • @spiri sagte in Implizite Konversion von zwei Klassen aus einer Library:

    Wenn beide Vektoren nur sagen wir mal drei Integer (x, y, z) beinhalten, diese in der gleichen Reihenfolge definiert sind (int x, y, z) und vom gleichen Typ kommen könntest du einfach einen schmutzigen C-Cast machen.

    reinterpret_cast<> würde ich immer vorziehen, alleine schon, um so etwas schmutziges zu kennzeichnen.

    Ansonsten kannst du noch einfach eine neue Klasse erstellen, die von der einen Library-Klasse public erbt und du implementierst einfach nur einen cast-operator neu und lässt den Rest so, wie er ist.

    Den vector_cast halte ich aber vermutlich fast für die einfachste und schönste Lösung.



  • @spiri sagte in Implizite Konversion von zwei Klassen aus einer Library:

    Wenn beide Vektoren nur sagen wir mal drei Integer (x, y, z) beinhalten, diese in der gleichen Reihenfolge definiert sind (int x, y, z) und vom gleichen Typ kommen könntest du einfach einen schmutzigen C-Cast machen.

    Das ist dann bloss dummerweise undefiniertes Verhalten 🔥 Wenn garantiert ist dass die Klassen layoutkompatibel sind sowie diverse andere Voraussetzungen erfüllen, dann könnte man mit memcpy kopieren.



  • @hustbaer sagte in Implizite Konversion von zwei Klassen aus einer Library:>

    Das ist dann bloss dummerweise undefiniertes Verhalten 🔥 Wenn garantiert ist dass die Klassen layoutkompatibel sind sowie diverse andere Voraussetzungen erfüllen, dann könnte man mit memcpy kopieren.

    Wo sollte da im Gegenzug von memcmp denn ein Unterschied sein, funktioniert doch
    https://ideone.com/x1DTu0



  • @spiri sagte in Implizite Konversion von zwei Klassen aus einer Library:

    Wo sollte da im Gegenzug von memcmp denn ein Unterschied sein, funktioniert doch
    https://ideone.com/x1DTu0

    Da wo der Standard sagt dass das eine definiertes Verhalten hat und das andere ... nicht. Ist mir im Moment aber echt zu mühsam ein Beispiel für dich zusammenzuschreiben anhand dessen du sehen kannst wie da Unsinn passieren kann.

    Weil es nebenbei auch nicht um konkrete Beispiele geht wo/wie Unsinn passieren kann, sondern schlicht und ergreifend darum dass der Standard sagt es ist undefiniert. Denn sobald er das sagt kannst du dir einfach nicht mehr sicher sein dass es "eh trotzdem gehen wird".

    ps: Und memcpy und memcmp sind zwei sehr verschiedene Funktionen. Mit memcmp kann man ganz sicher nichts kopieren.



  • Related: Boost Mutant


Log in to reply