Topic: Contravariant parameter types and function overriding


Author: jefolts@oasis.novia.net (Jeff Folts)
Date: 1997/04/23
Raw View
Jeff Folts (jefolts@oasis.novia.net) wrote:
> Nicolas Chapados (chapados@nortel.ca) wrote:
> > I would like some insight as to why C++ does not support contravariance
> > of the parameter types of overridden virtual functions.
>
> There is a fairly good explanation of why this was
> not done in:
>
>    "The Design and Evolution of C++", Bjarne Stroustrup
>         Section 13.7.1 - Relaxation of Argument Rules

Sorry, my response above refers to covariance and not
contravariance.  :-(
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: Valentin Bonnard <bonnardv@pratique.fr>
Date: 1997/04/19
Raw View
Herb Sutter <herbs@cntc.com> writes:

> "Nicolas Chapados" <chapados@nortel.ca> wrote:
> >class A { ... };
> >class B : public A { ... };
> >
> >class X            { virtual void foo(B*); };
> >class Y : public X { virtual void foo(A*); };
> >
> >In the above, why does not C++ allow Y::foo to override X::foo?  This
> >situation is type-safe: the derived function called through a base
> >pointer will always be passed a B*, which IS-An A*.
>
> I wasn't around when this was discussed, but my first gut reaction is that it
> can be done without additional language support using a forwarding function:

class Y : public X {
    virtual void foo(B* p) { foo (convert<A*>(p)); }
    virtual void foo(A*);
};

This argument also apply to covariance:

class X {
    virtual A* fooA() { return foo (); }
    A* foo();
};

class Y : public X {
    virtual A* fooA() { return fooB (); } // final - don't override
    virtual B* fooB() { return foo (); }
    B* foo();
};

class Z : public Y {
    virtual B* fooB() { return fooC (); } // final - don't override
    virtual C* fooC() { return foo (); }
    C* foo();
};

> On the other hand, I believe [covariant] return types were specifically
> allowed in the language at least in part because there was no easy way to get
> the same effect without a language extension, and it was a useful effect
> (e.g., it got rid of two thirds of the casts in one large multi-100KLOC
> project).

For functions like clone, a template can be used:

template <class T>
T*  clone (T* x)
{
    return static_cast<T*> (x.clone ()); // only one cast here
}

assuming all clone function are overiden to return something
of the type they are applied on.

--

Valentin Bonnard
mailto:bonnardv@pratique.fr
http://www.pratique.fr/~bonnardv (Informations sur le C++ en Francais)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: herbs@cntc.com (Herb Sutter)
Date: 1997/04/15
Raw View

"Nicolas Chapados" <chapados@nortel.ca> wrote:
>class A { ... };
>class B : public A { ... };
>
>class X            { virtual void foo(B*); };
>class Y : public X { virtual void foo(A*); };
>
>In the above, why does not C++ allow Y::foo to override X::foo?  This
>situation is type-safe: the derived function called through a base
>pointer will always be passed a B*, which IS-An A*.

I wasn't around when this was discussed, but my first gut reaction is that it
can be done without additional language support using a forwarding function:

    class Y : public X {
        virtual void foo(B* p) { foo(static_cast<A*>(p)); }
        virtual void foo(A*);
    };

Clumsier, but it works.  See D&E pages 295-297 for some related discussion
about this.

On the other hand, I believe contravariant return types were specifically
allowed in the language at least in part because there was no easy way to get
the same effect without a language extension, and it was a useful effect
(e.g., it got rid of two thirds of the casts in one large multi-100KLOC
project).

---
Herb Sutter (mailto:herbs@cntc.com)

Current Network Technologies Corp. (http://www.cntc.com)
2695 North Sheridan Way, Suite 150, Mississauga ON Canada   L5K 2N6
Tel 416-805-9088   Fax 905-822-3824
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: herbs@cntc.com (Herb Sutter)
Date: 1997/04/15
Raw View
herbs@cntc.com (Herb Sutter) wrote:
>On the other hand, I believe contravariant return types were specifically
                              ^^^^^^
Typo... this should be "covariant" of course.

---
Herb Sutter (mailto:herbs@cntc.com)

Current Network Technologies Corp. (http://www.cntc.com)
2695 North Sheridan Way, Suite 150, Mississauga ON Canada   L5K 2N6
Tel 416-805-9088   Fax 905-822-3824
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: jefolts@oasis.novia.net (Jeff Folts)
Date: 1997/04/15
Raw View
Nicolas Chapados (chapados@nortel.ca) wrote:
> I would like some insight as to why C++ does not support contravariance
> of the parameter types of overridden virtual functions.

There is a fairly good explanation of why this was
not done in:

   "The Design and Evolution of C++", Bjarne Stroustrup
        Section 13.7.1 - Relaxation of Argument Rules

It basically says that it would be too expensive to
check run-time type information on every argument of
virtual function calls . . . and that RTTI should be
explicitly employed where this functionality is
required.     B-)
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]





Author: "Nicolas Chapados" <chapados@nortel.ca>
Date: 1997/04/14
Raw View
I would like some insight as to why C++ does not support contravariance
of the parameter types of overridden virtual functions.  For example,
consider the following parallel hierarchies:

class A { ... };
class B : public A { ... };

class X            { virtual void foo(B*); };
class Y : public X { virtual void foo(A*); };

In the above, why does not C++ allow Y::foo to override X::foo?  This
situation is type-safe: the derived function called through a base
pointer
will always be passed a B*, which IS-An A*.

I am aware that the language has been modified to permit covariant
return types. Why not go further, and permit contravariant parameter
types?
[[An hypothesis is that permitting it would make the already-complex
overload resolution rules even more complex.]]

I would appreciate opinions from language historians and lawyers.

   Many thanks!
 + Nicolas Chapados

---
Nicolas Chapados   Home: n.chapados@ieee.ca
Nortel Technology, Montreal, Canada Work: chapados@nortel.ca
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]