unique_ptr, Konvertierung?



  • Hi!
    Ich benutze C++14.
    Problem:

    #include <memory>
    
    template <typename Op, typename T>
    struct base { };
    
    template <typename Mode, typename T>
    struct derived { };
    
    // int-Spezialisierung
    template <typename T>
    struct derived<int, T> : public base<derived<int, T>, T> { }; // CRTP pattern
    
    // geht nicht
    template <typename D, typename T>
    void fun(std::unique_ptr<base<D, T>>) { }
    
    // geht
    template <typename D, typename T>
    void fun(base<D, T>*) { }
    
    int main() {
        auto d = std::make_unique<derived<int, double>>();
        fun(std::move(d)); // Fehler
        fun(d.get()); // ok
    }
    

    Siehe http://ideone.com/UsAsXm

    Mit normalen Zeigern kann ich derived in base konvertieren, unique_ptr schafft das in diesem Fall nicht. Kann ich dem Typsystem irgendwie auf die Sprünge helfen?



  • Woher soll denn der Compiler wissen wie er std::unique_ptr<derived<int, double>> zu std::unique_ptr<base<derived<int, double>, double> konvertieren soll? Da fehlt der Konstruktor in der std::unique_ptr Klasse für.
    Und ob das mit der Typededuction hier

    template <typename D, typename T>
    void fun(std::unique_ptr<base<D, T>>) { }
    

    So funktioniert, wie du dir das vorstellst glaub ich auch nicht, vielleicht kann das noch jemand anderes besser erklären 😮



  • Mr.Long schrieb:

    Woher soll denn der Compiler wissen wie er std::unique_ptr<derived<int, double>> zu std::unique_ptr<base<derived<int, double>, double> konvertieren soll? Da fehlt der Konstruktor in der std::unique_ptr Klasse für.

    Unsinn, da fehlt gar kein Konstruktor.
    http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr
    (6)

    Mr.Long schrieb:

    Und ob das mit der Typededuction hier

    template <typename D, typename T>
    void fun(std::unique_ptr<base<D, T>>) { }
    

    So funktioniert, wie du dir das vorstellst glaub ich auch nicht, vielleicht kann das noch jemand anderes besser erklären 😮

    Das wird das eigentliche Problem sein schätze ich.


  • Mod

    Mr.Long schrieb:

    Da fehlt der Konstruktor in der std::unique_ptr Klasse für.

    Der existiert.

    Mr.Long schrieb:

    Und ob das mit der Typededuction hier

    template <typename D, typename T>
    void fun(std::unique_ptr<base<D, T>>) { }
    

    So funktioniert, wie du dir das vorstellst glaub ich auch nicht, vielleicht kann das noch jemand anderes besser erklären 😮

    Das ist ja auch das Problem. Eine solch allgemeine Deduktionsregel kann gar nicht existieren, da der Compiler potentiell jede beliebige Kombination von Templateargumenten testen müsste, um herauszufinden, ob eine davon zufällig über eine passable Konvertierung verfügt.

    Hier muss also vom Programmierer nachgeholfen werden. z.B.

    template <typename T>
    std::unique_ptr<base<derived<int, T>, T>> to_base(std::unique_ptr<derived<int, T>> p)
    {
        return std::move(p);
    }
    ...
        fun(to_base(std::move(d)));
    


  • Danke für eure Hilfe.


Anmelden zum Antworten