Jump to page: 1 2
Thread overview
Bug: Co-variance reported with different calling convention
Jul 22, 2003
Matthew Wilson
Re: Co-variance reported with different calling convention
Jul 22, 2003
Matthew Wilson
Jul 22, 2003
Russ Lewis
Jul 24, 2003
Matthew Wilson
Jul 28, 2003
Farmer
Jul 29, 2003
Matthew Wilson
Jul 29, 2003
Matthew Wilson
Re: Co-variance reported with different calling convention
Aug 30, 2003
Walter
Aug 30, 2003
Matthew Wilson
Aug 30, 2003
Walter
Sep 01, 2003
Walter
Sep 01, 2003
Matthew Wilson
Sep 02, 2003
Walter
July 22, 2003
class X
{
    extern(Windows):
    void x()
    {
        printf("X::x()\n");
    }
}

class Y
    : X
{
    void x()
    {
        printf("Y::x()\n");
    }
}


"combase_test.d(51): function x overrides but is not covariant with x"


I strongly suspect that this is not just an omission, but something that has been discussed and is a deliberate behaviour. If that is so, can someone enlighten me as to the rationale?

:)

Matthew


July 22, 2003
> I strongly suspect that this is not just an omission, but something that
has
> been discussed and is a deliberate behaviour. If that is so, can someone enlighten me as to the rationale?

Of course, even if it deliberately cannot intuit the calling convention, the error message is still wrong. (Unless one counts co-variance to include calling convention, of course ...)


July 22, 2003
I assume the problem is the same as if you had overloaded the function with one with a different return value.  The two functions have the same calling parameters, but they have different signatures.  A calling function that is expecting extern(Windows) but gets the non-extern version will break, and vice-versa.

Matthew Wilson wrote:
> class X
> {
>     extern(Windows):
>     void x()
>     {
>         printf("X::x()\n");
>     }
> }
> 
> class Y
>     : X
> {
>     void x()
>     {
>         printf("Y::x()\n");
>     }
> }
> 
> 
> "combase_test.d(51): function x overrides but is not covariant with x"
> 
> 
> I strongly suspect that this is not just an omission, but something that has
> been discussed and is a deliberate behaviour. If that is so, can someone
> enlighten me as to the rationale?
> 
> :)
> 
> Matthew
> 
> 

July 24, 2003
I get that. My point was that it either doesn't make sense, or is arbitrarily strict, depending on one's viewpoint.

Further, this will run into problems with templates, when one wants to use bolt-ins (which is precisely what I was laying the groundwork for with the work that precipitated the error), and will thus dramatically complicate the lives of template library writers.

If anyone can see a significant +ve to the current behaviour, please tell, and I'll know to abandon this quest, otherwise I'll have to keep banging on about it until something gives. (That something is, of course, you Walter! <@>)

"Russ Lewis" <spamhole-2001-07-16@deming-os.org> wrote in message news:bfje0h$1jlo$1@digitaldaemon.com...
> I assume the problem is the same as if you had overloaded the function with one with a different return value.  The two functions have the same calling parameters, but they have different signatures.  A calling function that is expecting extern(Windows) but gets the non-extern version will break, and vice-versa.
>
> Matthew Wilson wrote:
> > class X
> > {
> >     extern(Windows):
> >     void x()
> >     {
> >         printf("X::x()\n");
> >     }
> > }
> >
> > class Y
> >     : X
> > {
> >     void x()
> >     {
> >         printf("Y::x()\n");
> >     }
> > }
> >
> >
> > "combase_test.d(51): function x overrides but is not covariant with x"
> >
> >
> > I strongly suspect that this is not just an omission, but something that
has
> > been discussed and is a deliberate behaviour. If that is so, can someone enlighten me as to the rationale?
> >
> > :)
> >
> > Matthew
> >
> >
>



July 28, 2003
Hi Matthew,

you wrote:
>> > class X
>> > {
>> >     extern(Windows):
>> >     void x()
>> >     {
>> >         printf("X::x()\n");
>> >     }
>> > }
>> >
>> > class Y
>> >     : X
>> > {
>> >     void x()
>> >     {
>> >         printf("Y::x()\n");
>> >     }
>> > }

As you know, any occurence of class X must be substitutable for class Y.
This must be true from a designer's perspective *and* from the compiler's
view. But due to the different calling convention of X.x() and Y.x(),
calling Y.x() instead of X.x() is not possible in a straight way. Yes, the
compiler could generate code to make it work (behind your back), but the
programmer could easily make that, too.

> Further, this will run into problems with templates, when one wants to use bolt-ins (which is precisely what I was laying the groundwork for with the work that precipitated the error), and will thus dramatically complicate the lives of template library writers.

Have you link at hand for an article about bolt-ins (from you)?
I enjoyed that one about shims.





Farmer.


July 29, 2003
> Have you link at hand for an article about bolt-ins (from you)?

Alas no. You may have to wait for the book. ;)  (I'm doing those chapters at
the moment.)

> I enjoyed that one about shims.

Please to hear it.



July 29, 2003
> Please to hear it.

Pleased to hear it, I meant



August 30, 2003
The problem is that the calling conventions for X.x and Y.x are different, yet being virtual, they must have the same calling convention.

"Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bfj6h0$1cbf$1@digitaldaemon.com...
>
> class X
> {
>     extern(Windows):
>     void x()
>     {
>         printf("X::x()\n");
>     }
> }
>
> class Y
>     : X
> {
>     void x()
>     {
>         printf("Y::x()\n");
>     }
> }
>
>
> "combase_test.d(51): function x overrides but is not covariant with x"
>
>
> I strongly suspect that this is not just an omission, but something that
has
> been discussed and is a deliberate behaviour. If that is so, can someone enlighten me as to the rationale?
>
> :)
>
> Matthew
>
>


August 30, 2003
Well of course. We need a solution.

I would very much like the following:

1. That Y.x is automatically deduced to be of type extern(Windows). Since D does not allow non-virtuals, this seems the best way. And consider what happens when Y is a template! Are we saying some superbly useful veneer template (to shamelessly use my own terminology) can be restricted to classes with matching methods of only one calling-convention? That totally sucks

2. A corollary is that calling convention should be "promoted" to something more inate in the language, so that I could write a template such as the following (in pseudo-C++, since my D templating is a little rusty):

    T is assumed to be an interface on which (pure virtual) lock() and
unlock() methods are defined. We want a template that will work with any
calling convention

    template <typename T>
    class ref_counter
      : public T
    {
    public:
      template<callconv C>
      extern (C)
      void C lock()
      {
        . . .
      }
      template<callconv C>
      extern (C)
      void C unlock()
      {
        . . .
      }
    };

Now this works with

    struct ICDeclRefCounter
    {
      virtual void __cdecl lock() = 0;
      virtual void __cdecl unlock() = 0;
    };

    struct IStdCallRefCounter
    {
      virtual void __stdcall lock() = 0;
      virtual void __stdcall unlock() = 0;
    };

etc. etc.

This is the most truculent imperfection in C++, and I f***ing hate it. It would be a stunning victory for D to handle this in the language proper, rather than having to use shims, or similar, workarounds.

Nice challenge? ;)


"Walter" <walter@digitalmars.com> wrote in message news:bip6lh$17hg$1@digitaldaemon.com...
> The problem is that the calling conventions for X.x and Y.x are different, yet being virtual, they must have the same calling convention.
>
> "Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bfj6h0$1cbf$1@digitaldaemon.com...
> >
> > class X
> > {
> >     extern(Windows):
> >     void x()
> >     {
> >         printf("X::x()\n");
> >     }
> > }
> >
> > class Y
> >     : X
> > {
> >     void x()
> >     {
> >         printf("Y::x()\n");
> >     }
> > }
> >
> >
> > "combase_test.d(51): function x overrides but is not covariant with x"
> >
> >
> > I strongly suspect that this is not just an omission, but something that
> has
> > been discussed and is a deliberate behaviour. If that is so, can someone enlighten me as to the rationale?
> >
> > :)
> >
> > Matthew
> >
> >
>
>


August 30, 2003
Converting one calling convention to another would require the compiler to generate a function to do it, as in:

    int foo(int a, int b, int c)
    {
        int theotherfoo(int a, b, c);
    }

Your item 1 may be the best solution.

"Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bipcba$1g74$1@digitaldaemon.com...
> Well of course. We need a solution.
>
> I would very much like the following:
>
> 1. That Y.x is automatically deduced to be of type extern(Windows). Since
D
> does not allow non-virtuals, this seems the best way. And consider what happens when Y is a template! Are we saying some superbly useful veneer template (to shamelessly use my own terminology) can be restricted to classes with matching methods of only one calling-convention? That totally sucks
>
> 2. A corollary is that calling convention should be "promoted" to
something
> more inate in the language, so that I could write a template such as the following (in pseudo-C++, since my D templating is a little rusty):
>
>     T is assumed to be an interface on which (pure virtual) lock() and
> unlock() methods are defined. We want a template that will work with any
> calling convention
>
>     template <typename T>
>     class ref_counter
>       : public T
>     {
>     public:
>       template<callconv C>
>       extern (C)
>       void C lock()
>       {
>         . . .
>       }
>       template<callconv C>
>       extern (C)
>       void C unlock()
>       {
>         . . .
>       }
>     };
>
> Now this works with
>
>     struct ICDeclRefCounter
>     {
>       virtual void __cdecl lock() = 0;
>       virtual void __cdecl unlock() = 0;
>     };
>
>     struct IStdCallRefCounter
>     {
>       virtual void __stdcall lock() = 0;
>       virtual void __stdcall unlock() = 0;
>     };
>
> etc. etc.
>
> This is the most truculent imperfection in C++, and I f***ing hate it. It would be a stunning victory for D to handle this in the language proper, rather than having to use shims, or similar, workarounds.
>
> Nice challenge? ;)
>
>
> "Walter" <walter@digitalmars.com> wrote in message news:bip6lh$17hg$1@digitaldaemon.com...
> > The problem is that the calling conventions for X.x and Y.x are
different,
> > yet being virtual, they must have the same calling convention.
> >
> > "Matthew Wilson" <matthew@stlsoft.org> wrote in message news:bfj6h0$1cbf$1@digitaldaemon.com...
> > >
> > > class X
> > > {
> > >     extern(Windows):
> > >     void x()
> > >     {
> > >         printf("X::x()\n");
> > >     }
> > > }
> > >
> > > class Y
> > >     : X
> > > {
> > >     void x()
> > >     {
> > >         printf("Y::x()\n");
> > >     }
> > > }
> > >
> > >
> > > "combase_test.d(51): function x overrides but is not covariant with x"
> > >
> > >
> > > I strongly suspect that this is not just an omission, but something
that
> > has
> > > been discussed and is a deliberate behaviour. If that is so, can
someone
> > > enlighten me as to the rationale?
> > >
> > > :)
> > >
> > > Matthew
> > >
> > >
> >
> >
>
>


« First   ‹ Prev
1 2