D - Bug: Co-variance reported with different calling convention
- "Matthew Wilson" <matthew stlsoft.org> Jul 22 2003
- "Matthew Wilson" <matthew stlsoft.org> Jul 22 2003
- Russ Lewis <spamhole-2001-07-16 deming-os.org> Jul 22 2003
- "Matthew Wilson" <matthew stlsoft.org> Jul 24 2003
- Farmer <itsFarmer. freenet.de> Jul 28 2003
- "Matthew Wilson" <matthew stlsoft.org> Jul 29 2003
- "Matthew Wilson" <matthew stlsoft.org> Jul 29 2003
- "Walter" <walter digitalmars.com> Aug 29 2003
- "Matthew Wilson" <matthew stlsoft.org> Aug 29 2003
- "Walter" <walter digitalmars.com> Aug 30 2003
- "Riccardo De Agostini" <riccardo.de.agostini email.it> Sep 01 2003
- "Walter" <walter digitalmars.com> Sep 01 2003
- "Matthew Wilson" <dmd synesis.com.au> Sep 01 2003
- "Riccardo De Agostini" <riccardo.de.agostini email.it> Sep 01 2003
- "Walter" <walter digitalmars.com> Sep 02 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
Jul 22 2003
I strongly suspect that this is not just an omission, but something that
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 ...)
Jul 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
Jul 22 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
been discussed and is a deliberate behaviour. If that is so, can someone enlighten me as to the rationale? :) Matthew
Jul 24 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.
Jul 28 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.
Jul 29 2003
Please to hear it.
Pleased to hear it, I meant
Jul 29 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
been discussed and is a deliberate behaviour. If that is so, can someone enlighten me as to the rationale? :) Matthew
Aug 29 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
been discussed and is a deliberate behaviour. If that is so, can someone
enlighten me as to the rationale?
:)
Matthew
Aug 29 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
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
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
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
has
been discussed and is a deliberate behaviour. If that is so, can
enlighten me as to the rationale?
:)
Matthew
Aug 30 2003
"Walter" <walter digitalmars.com> ha scritto nel messaggio news:biphsq$1o9r$1 digitaldaemon.com...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.
What about performance? Is it maybe better to explicitly enable, or being able to disable, calling performance deduction via a compiler flag? Ric
Sep 01 2003
"Riccardo De Agostini" <riccardo.de.agostini email.it> wrote in message news:biuv93$nt2$1 digitaldaemon.com..."Walter" <walter digitalmars.com> ha scritto nel messaggio news:biphsq$1o9r$1 digitaldaemon.com...Converting one calling convention to another would require the compiler
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.
What about performance? Is it maybe better to explicitly enable, or being able to disable, calling performance deduction via a compiler flag?
While that's possible, I'm philosophically opposed to having compiler flags change the semantics of the language. There are innumerable such flags on typical C++ compilers, which cause endless problems.
Sep 01 2003
I don't want a compiler flag. I want the language to deduce the right behaviour for me. "Walter" <walter digitalmars.com> wrote in message news:biuvsu$on5$1 digitaldaemon.com..."Riccardo De Agostini" <riccardo.de.agostini email.it> wrote in message news:biuv93$nt2$1 digitaldaemon.com..."Walter" <walter digitalmars.com> ha scritto nel messaggio news:biphsq$1o9r$1 digitaldaemon.com...Converting one calling convention to another would require the
togenerate 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.
What about performance? Is it maybe better to explicitly enable, or
able to disable, calling performance deduction via a compiler flag?
While that's possible, I'm philosophically opposed to having compiler
change the semantics of the language. There are innumerable such flags on typical C++ compilers, which cause endless problems.
Sep 01 2003
"Walter" <walter digitalmars.com> ha scritto nel messaggio news:biuvsu$on5$1 digitaldaemon.com...While that's possible, I'm philosophically opposed to having compiler
change the semantics of the language. There are innumerable such flags on typical C++ compilers, which cause endless problems.
I agree on that. How about defining a finite (and very small) set of language feature subsets, thus giving us only one switch to select the desired subset, in order to, for instance, compile for a slower target (typically an embedded system) being sure that what the compiler does under the hood doesn't result in performance loss in critical sections of the code? The need arises, funny enough, from one of the best features in DMD, i.e. being free of the virtual keyword, not to mention calling-convention polymorphism... OTOH, I realize that defining the subsets is a good starting point for holy wars :-) besides being, maybe, unpractical for other reasons. I'd really like feedback on this from people more experienced than I... Ric
Sep 01 2003
"Riccardo De Agostini" <riccardo.de.agostini email.it> wrote in message news:biv4q0$v71$1 digitaldaemon.com..."Walter" <walter digitalmars.com> ha scritto nel messaggio news:biuvsu$on5$1 digitaldaemon.com...While that's possible, I'm philosophically opposed to having compiler
change the semantics of the language. There are innumerable such flags
typical C++ compilers, which cause endless problems.
I agree on that. How about defining a finite (and very small) set of language feature subsets, thus giving us only one switch to select the desired subset, in order to, for instance, compile for a slower target (typically an embedded system) being sure that what the compiler does
the hood doesn't result in performance loss in critical sections of the code?
You can make a function 'final' and it will be non-virtual.The need arises, funny enough, from one of the best features in DMD, i.e. being free of the virtual keyword, not to mention calling-convention polymorphism... OTOH, I realize that defining the subsets is a good starting point for
wars :-) besides being, maybe, unpractical for other reasons. I'd really like feedback on this from people more experienced than I... Ric
Sep 02 2003
"Walter" <walter digitalmars.com> ha scritto nel messaggio news:bj334s$ecp$1 digitaldaemon.com...You can make a function 'final' and it will be non-virtual.
While that may be a solution, or better a workaround, I don't think this is the purpose of "final" functions. Anyway, for the sake of consistent language semantics, I think I can live with automatic calling convention deduction after all. :) Ric
Sep 03 2003









"Matthew Wilson" <matthew stlsoft.org> 