contravariant argument types: wanna?
Steven Schveighoffer
schveiguy at yahoo.com
Tue Sep 22 18:15:54 PDT 2009
On Tue, 22 Sep 2009 20:07:22 -0400, Andrei Alexandrescu
<SeeWebsiteForEmail at erdani.org> wrote:
> Hello,
>
>
> Today, overriding functions have covariant return types:
>
> class A {
> A clone();
> }
>
> class B : A {
> B clone(); // fine, overrides A.clone
> }
>
> That is entirely principled and cool. Now the entire story is that
> overriding function may have not only covariant return types, but also
> contravariant argument types:
>
> class A {
> A fun(B);
> }
>
> class B : A {
> B fun(A); // fine (in theory), overrides A.fun
> }
>
> Today D does not support contravariant arguments, but Walter told me
> once he'd be quite willing to implement them. It is definitely the right
> thing to do, but Walter would want to see a compelling example before
> getting to work.
>
> Is there interest in contravariant argument types? If so, do you know of
> a killer example?
http://d.puremagic.com/issues/show_bug.cgi?id=3075
I thought Walter didn't want contravariance, maybe my clue was Walter
saying: "[Contravariance is] an attractive idea, but it's been considered
and rejected a couple of
times now."
But he may just have been talking about only doing contravariance on
delegates, maybe he's all for contravariance in the general case, but I
didn't think so.
I think the bug above is the killer example, implicit casting of delegates
would be *awesome*.
BTW, I don't see a huge benefit from your example. If B inherits from A,
then B knows about all the types A knows about (imagining an example where
the parameters were some other class hierarchy, like C and D), so does it
make a lot of sense to limit the arguments to B.fun to a base class of
something B must already know about? I mean, it's not like B doesn't know
about the derived type, how hard would it be to just use the derived
type? Maybe I'm missing something...
The other part of contravariance which bearophile brought up a while back
is contravariance (and covariance) of template parameters, that would also
be useful, but would require some annotation.
e.g.:
class C(in T) // means compiler enforces that C only ever uses T as an
input
{
void foo(T) {...}
}
class A {}
class B: A {}
void fun(C!B c) { auto b = new B; c.foo(b);}
void main()
{
auto c = new C!A
fun(c); // legal
}
A good example for C would be a comparator object.
But I think the absolute best usage is implicit delegate casting. That
should be a no-brainer in my mind.
-Steve
More information about the Digitalmars-d
mailing list