Covariant return types and MI

Discussion in 'C++' started by Robert Fendt, Mar 5, 2010.

  1. Robert Fendt

    Robert Fendt Guest

    Hi all,

    is this legal:

    class interf1
    {
    virtual ~interf1() {}
    virtual interf1* clone() = 0;
    };

    class interf2
    {
    vitual ~interf2() {}
    virtual interf2* clone() = 0;
    };

    class impl : public interf1, public interf2
    {
    impl* clone();
    };


    It seems to work at least in GCC 'pedantic ANSI' mode, and I
    think I recall something about covariant return types being
    explicitely allowed in standard C++. Cannot check with VC++
    right now...

    However, assuming that it is legal and well-defined: are there
    any hidden snares I should be aware of?

    Regards,
    Robert
    Robert Fendt, Mar 5, 2010
    #1
    1. Advertising

  2. On Mar 5, 10:37 am, Robert Fendt <> wrote:
    > Hi all,
    >
    > is this legal:
    >
    > class interf1
    > {
    >   virtual ~interf1() {}
    >   virtual interf1* clone() = 0;
    >
    > };
    >
    > class interf2
    > {
    >   vitual ~interf2() {}
    >   virtual interf2* clone() = 0;
    >
    > };
    >
    > class impl : public interf1, public interf2
    > {
    >   impl* clone();
    >
    > };
    >
    > It seems to work at least in GCC 'pedantic ANSI' mode, and I
    > think I recall something about covariant return types being
    > explicitely allowed in standard C++. Cannot check with VC++
    > right now...
    >
    > However, assuming that it is legal and well-defined: are there
    > any hidden snares I should be aware of?


    Yes. Visual studios, all versions AFAIK do not support covariant
    return types and multiple inheritance, or maybe virtual multiple
    inheritance. I suggest the following quoted from Alf P. Steinbach here
    http://groups.google.com/group/comp.lang.c /msg/e50bd48283d94bb2
    as a good workaround for this lack of support, though perhaps more
    costly on compilers which actually support it. (I don't know
    offhand.)

    <code>
    #include <string>
    #include <iostream>

    class base {
    protected:
    virtual base * virtual_clone() const = 0;
    public:
    virtual void do_x() { std::cout << "base::do_x()\n"; }
    virtual int * value() = 0;
    virtual ~base() {}
    base* clone() const { return virtual_clone(); }

    };

    class sub_base1
    : public virtual base
    {
    public:
    virtual void do_x() { std::cout << "sub_base1::do_x()\n"; }

    };

    class sub_base2
    : public virtual base
    {
    public:
    virtual void do_x() { std::cout << "sub_base2::do_x()\n"; }

    };

    class derived
    : public sub_base1
    , public sub_base2
    {
    protected:
    virtual base * virtual_clone() const { return new derived; }
    public:
    virtual void do_x() { std::cout << "derived::do_x()\n"; }
    derived* clone() const
    { return dynamic_cast<derived*>( virtual_clone() ); }
    int * value() { return 0; }

    };

    class sub_base3
    : public sub_base1
    {
    public:
    void do_x()
    {
    std::cout << "sub_base3::do_x() -> " << *value() << "\n";
    }
    sub_base3* clone() const
    { return dynamic_cast<sub_base3*>( virtual_clone() ); }

    };

    class derived2
    : public sub_base3
    {
    protected:
    virtual base * virtual_clone() const { return new
    derived2(*this); }
    public:
    void do_y() {}
    derived2 * clone() const
    { return dynamic_cast<derived2*>( virtual_clone() ); }
    int * value() { return val; }

    derived2(int * v) : val(v) {}
    private:
    int * val;

    };

    int main()
    {
    int x = 5;
    derived2 d(&x);
    d.do_x();
    //d.virtual_clone()->do_x();
    base * b = &d;
    b->do_x();

    base * b2 = b->clone();
    b2->do_x();

    sub_base3 * sb3 = dynamic_cast<sub_base3*>(b2);
    sb3->do_x();
    sub_base3 * sb32 = sb3->clone(); // this call doesn't explode.
    sb32->do_x();
    }

    </code>
    Joshua Maurice, Mar 5, 2010
    #2
    1. Advertising

  3. Robert Fendt

    Robert Fendt Guest

    And thus spake Joshua Maurice <>
    Fri, 5 Mar 2010 12:32:14 -0800 (PST):

    > Yes. Visual studios, all versions AFAIK do not support covariant
    > return types and multiple inheritance, or maybe virtual multiple
    > inheritance. I suggest the following quoted from Alf P. Steinbach here
    > http://groups.google.com/group/comp.lang.c /msg/e50bd48283d94bb2
    > as a good workaround for this lack of support, though perhaps more
    > costly on compilers which actually support it. (I don't know
    > offhand.)


    That workaround does not work for me, since my problem is not
    virtual inheritance. If I *had* a common base class, I would not
    need covariant return types, since in most cases it would be
    fine to just return a pointer to base.

    My problem is that I have *two* completely distinct abstract
    bases which both stipulate that implementations support a
    clone() method. On GCC, this seems to be no problem, and I find
    nothing in the language standard that says this is illegal (in
    fact, this scenario is IMHO exactly the reason to allow
    covariant types, which is why even Java supports them by now).

    Thankfully I do not have to deal with virtual inheritance here;
    maybe this means that it will work also in VC++. If not, I will
    have to change the structure to something like this:

    class interf1
    {
    virtual ~interf1() {}
    virtual interf1* clone_i1() = 0;
    };

    class interf2
    {
    vitual ~interf2() {}
    virtual interf2* clone_i2() = 0;
    };

    class impl : public interf1, public interf2
    {
    interf1* clone_i1() {return new impl(*this)};
    interf2* clone_i2() {return new impl(*this)};
    };

    ....which would be nothing but an ugly hack. Oh well, so what
    else is new. It's my own fault of course: I just *had* to have
    the ambition to support VC++. I should just say to the users of
    my library "get a real C++ compiler" and be done with it.

    Regards,
    Robert
    Robert Fendt, Mar 6, 2010
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Robert Elliot
    Replies:
    10
    Views:
    1,132
    Robert Elliot
    Jun 6, 2004
  2. Webb  Roberts

    Generics? Covariant return types?

    Webb Roberts, Nov 10, 2005, in forum: Java
    Replies:
    3
    Views:
    394
    Thomas Hawtin
    Nov 10, 2005
  3. Alex Vinokur
    Replies:
    7
    Views:
    504
    Karl Heinz Buchegger
    Apr 15, 2004
  4. Rob.
    Replies:
    9
    Views:
    392
    Alf P. Steinbach
    Jun 26, 2004
  5. Martin Stettner

    Covariant return types

    Martin Stettner, Jan 30, 2005, in forum: C++
    Replies:
    8
    Views:
    485
    Bogdan Sintoma
    Feb 1, 2005
Loading...

Share This Page