• Covariance and xxx_ptr

    From Javier@21:1/5 to All on Sat Mar 5 07:00:41 2016
    { edited to shorten lines to ~70 characters (except code). -mod }

    Consider:

    struct Consumer {
    virtual Provider* use();
    };

    struct ConcreteConsumer {
    ConcreteProvider* use() override {...}
    };

    struct Provider {...};
    struct ConcreteProvider : public Provider {...}

    The covariant return type is just fine, thank you very much. However, if
    I want to create something like:

    struct Consumer {
    virtual unique_ptr<Provider> use();
    };

    struct ConcreteConsumer {
    unique_ptr<ConcreteProvider> use() override {...}
    };

    struct Provider {...};
    struct ConcreteProvider : public Provider {...}

    Cannot be done. I understand the reason, but it seems to me unintuitive
    that covariance does not "port" when using any of the std::xxx_ptr
    types.
    Furthermore, a corresponding implementation for ConcreteConsumer would
    have to look like this to type derived from Provider:

    struct ConcreteConsumer {
    unique_ptr<Provider> use() override { return unique_ptr<Provider>{make_unique<ConcreteProvider>();}
    };


    In essence, I think that std::is_convertible<xxx_ptr<Derived>, xxx_ptr<Base>>should succeed in the same way that
    std::is_convertible<Derived*, Base*> succeeds, and overriding a member
    function that returns xxx_ptr where the types are covariant should be
    allowed.

    Are there technical limitations? Seems to me that no abstractions would
    be broken.

    Regards,
    --Javier


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?ISO-8859-1?Q?=D6=F6_Tiib?=@21:1/5 to Javier on Mon Mar 7 12:11:55 2016
    On Saturday, 5 March 2016 15:10:09 UTC+2, Javier wrote:

    The covariant return type is just fine, thank you very much. However, if
    I want to create something like:

    struct Consumer {
    virtual unique_ptr<Provider> use();
    };

    struct ConcreteConsumer {
    unique_ptr<ConcreteProvider> use() override {...}
    };

    struct Provider {...};
    struct ConcreteProvider : public Provider {...}

    Cannot be done. I understand the reason, but it seems to me unintuitive
    that covariance does not "port" when using any of the std::xxx_ptr
    types.

    In some other context also covariance of 'vector<Provider>' and 'vector<ConcreteProvider>' (or iterators to such) may feel like
    intuitively making sense.

    Simulation of covariance (where it makes sense) can be made manually
    by using private virtual 'doUse()' and public non-virtual 'use()' that calls 'doUse()' and converts its return type. The 3-4 additional lines per class
    are not that much if you need it and if you don't need it then YAGNI.

    Furthermore, a corresponding implementation for ConcreteConsumer would
    have to look like this to type derived from Provider:

    struct ConcreteConsumer {
    unique_ptr<Provider> use() override { return unique_ptr<Provider>{make_unique<ConcreteProvider>();}
    };


    In essence, I think that std::is_convertible<xxx_ptr<Derived>, xxx_ptr<Base>>should succeed in the same way that std::is_convertible<Derived*, Base*> succeeds, and overriding a member function that returns xxx_ptr where the types are covariant should be allowed.

    The inbuilt covariance is only for raw pointers and references and there are
    no covariance of class type objects (that smart pointers are). Covariance is about inheritance and not about convertibility but converting objects of derived class into object of base class means object slicing so it has to be
    a pointer or reference.

    Smart pointers indeed manage to simulate covariance somewhat with
    conversion assignment templates and conversion constructor templates
    in order to be more similar to raw pointers.


    Are there technical limitations? Seems to me that no abstractions would
    be broken.

    Turning all implicit convertibility into covariance is likely bad idea. Implicit convertibility often confuses programmers and it does not
    need to have more ways of application. Adding some "magic"
    specially to smart pointers is likely even worse since these would
    then be core language features that only look like library classes.


    --
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]
    [ comp.lang.c++.moderated. First time posters: Do this! ]

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)