Error C2392 is hitting me hard!
I have a managed C++ library that implements a bunch of fixed interfaces.
For example, one interface is:
public abstract interface IDbCommand
{
public abstract new System.Data.IDbConnection Connection [ get, set ]
}
and I am forced to implement:
public __gc class MyCommand : public IDbCommand
{
__property IDbConnection* get_Connection();
__property void set_Connection(IDbConnection* value);
}
instead of what I really want, which is:
public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}
This has been an annoyance in that consumers of my library have to cast
things to the derived types in order to use them. But it is turning into a
MAJOR PROBLEM now that I am doing Visual Studio.NET integration. VS.NET
bases design time behavior (such as code generation) on the types of
components/properties and thier attributes. I have had several cases where
I can not get VS.NET to read my attributes because it thinks it has an
IDbConnection instead of a MyConnection.
Are there any workarounds at all to the covariant return type problem?
Thanks!
-Steve 13 4190
Stephen,
Unfortunately I'm not sure how to in C++, I wanted to let you know how to in
C# or VB.NET, in case it offers some hints for you to pursue.
In C# you use "Explicit interface member implementations" http://msdn.microsoft.com/library/de...pec_13_4_1.asp
In VB.NET you can change the name of the implementing function and make it
private to get the same effect as C#.
I have not delved deep enough into C++ yet to know how here.
Hope this helps
Jay
"Stephen Walch" <sw****@proposion.com> wrote in message
news:OB**************@tk2msftngp13.phx.gbl... Error C2392 is hitting me hard!
I have a managed C++ library that implements a bunch of fixed interfaces. For example, one interface is:
public abstract interface IDbCommand { public abstract new System.Data.IDbConnection Connection [ get,
set ] }
and I am forced to implement:
public __gc class MyCommand : public IDbCommand { __property IDbConnection* get_Connection(); __property void set_Connection(IDbConnection* value); }
instead of what I really want, which is:
public __gc class MyCommand : public IDbCommand { __property MyConnection* get_Connection(); __property void set_Connection(MyConnection* value); }
This has been an annoyance in that consumers of my library have to cast things to the derived types in order to use them. But it is turning into
a MAJOR PROBLEM now that I am doing Visual Studio.NET integration. VS.NET bases design time behavior (such as code generation) on the types of components/properties and thier attributes. I have had several cases
where I can not get VS.NET to read my attributes because it thinks it has an IDbConnection instead of a MyConnection.
Are there any workarounds at all to the covariant return type problem? Thanks!
-Steve
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:es**************@TK2MSFTNGP10.phx.gbl... Stephen, Unfortunately I'm not sure how to in C++, I wanted to let you know how to in C# or VB.NET, in case it offers some hints for you to pursue.
In C# you use "Explicit interface member implementations"
Managed C++ does not support explicit interface implementation, and the CLR
does not support covariant return. In C#, you can use explicit interface
implementation to simulate covariant return, but it is a dirty hack, and your
class will become unusable as a base class for Managed C++ users.
Unfortunately there is not a good solution to the OP's question while
remaining in Managed C++. Probably the least painful solution would be to
write the classes that use pseudo-covariant return in C#. Managed C++ should
still be able to consume those classes, even if you can't derive off of them.
Ken
Ken, your class will become unusable as a base class for Managed C++ users.
Will Managed C++ have the same issue with VB.NET classes that make the
implementing function private? I know at the IL level the C# & VB.NET
technique are slightly different, while having the same net effect.
Out of curiosity why is it that Managed C++ cannot derive from them? I
realize that the method of the interface itself is now hidden, I would not
expect that to preclude you from inheriting from it.
Thanks
Jay
"Ken Alverson" <US********@Alverson.net> wrote in message
news:O5*************@TK2MSFTNGP11.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in
message news:es**************@TK2MSFTNGP10.phx.gbl... Stephen, Unfortunately I'm not sure how to in C++, I wanted to let you know how
to in C# or VB.NET, in case it offers some hints for you to pursue.
In C# you use "Explicit interface member implementations" Managed C++ does not support explicit interface implementation, and the
CLR does not support covariant return. In C#, you can use explicit interface implementation to simulate covariant return, but it is a dirty hack, and
your class will become unusable as a base class for Managed C++ users.
Unfortunately there is not a good solution to the OP's question while remaining in Managed C++. Probably the least painful solution would be to write the classes that use pseudo-covariant return in C#. Managed C++
should still be able to consume those classes, even if you can't derive off of
them. Ken
Can you tell me more about this "dirty hack"? I do not minf making my
classes final; I just want managed applications that use my library to see
the more-derived returned types. Can you give me an example, perhaps based
on my original problem. Deriving from:
public abstract interface IDbCommand
{
public abstract new System.Data.IDbConnection Connection [ get, set ]
}
what I want clients to see:
public __gc class MyCommand : public IDbCommand
{
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
}
Thanks again.
"Ken Alverson" <US********@Alverson.net> wrote in message
news:O5*************@TK2MSFTNGP11.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in
message news:es**************@TK2MSFTNGP10.phx.gbl... Stephen, Unfortunately I'm not sure how to in C++, I wanted to let you know how
to in C# or VB.NET, in case it offers some hints for you to pursue.
In C# you use "Explicit interface member implementations" Managed C++ does not support explicit interface implementation, and the
CLR does not support covariant return. In C#, you can use explicit interface implementation to simulate covariant return, but it is a dirty hack, and
your class will become unusable as a base class for Managed C++ users.
Unfortunately there is not a good solution to the OP's question while remaining in Managed C++. Probably the least painful solution would be to write the classes that use pseudo-covariant return in C#. Managed C++
should still be able to consume those classes, even if you can't derive off of
them. Ken
Stephen,
I believe the "dirty hack" that Ken was referring to is what C# does, which
is specific to C#.
C# hides the implementation of the IDbCommand.Connection method, then you
can define Connection property with the return type you want.
I want to say the closest thing in C++ would be ATL's tear-off interface,
although I never did really figure out how those work. Also I'm not sure you
can do a tear-off interface in Managed C++.
Hope this helps
Jay
"Stephen Walch" <sw****@proposion.com> wrote in message
news:uQ**************@TK2MSFTNGP12.phx.gbl... Can you tell me more about this "dirty hack"? I do not minf making my classes final; I just want managed applications that use my library to see the more-derived returned types. Can you give me an example, perhaps
based on my original problem. Deriving from:
public abstract interface IDbCommand { public abstract new System.Data.IDbConnection Connection [ get,
set ] }
what I want clients to see:
public __gc class MyCommand : public IDbCommand { __property MyConnection* get_Connection(); __property void set_Connection(MyConnection* value); }
Thanks again.
"Ken Alverson" <US********@Alverson.net> wrote in message news:O5*************@TK2MSFTNGP11.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message news:es**************@TK2MSFTNGP10.phx.gbl... Stephen, Unfortunately I'm not sure how to in C++, I wanted to let you know how to in C# or VB.NET, in case it offers some hints for you to pursue.
In C# you use "Explicit interface member implementations"
Managed C++ does not support explicit interface implementation, and the CLR does not support covariant return. In C#, you can use explicit
interface implementation to simulate covariant return, but it is a dirty hack, and your class will become unusable as a base class for Managed C++ users.
Unfortunately there is not a good solution to the OP's question while remaining in Managed C++. Probably the least painful solution would be
to write the classes that use pseudo-covariant return in C#. Managed C++ should still be able to consume those classes, even if you can't derive off of them. Ken
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:OA****************@tk2msftngp13.phx.gbl... Ken, your class will become unusable as a base class for Managed C++ users. Will Managed C++ have the same issue with VB.NET classes that make the implementing function private? I know at the IL level the C# & VB.NET technique are slightly different, while having the same net effect.
I honestly don't know, but I would suspect the effect would be the same.
Out of curiosity why is it that Managed C++ cannot derive from them? I realize that the method of the interface itself is now hidden, I would not expect that to preclude you from inheriting from it.
Well, specifically, you can't override the pseudo-covariant function (which is
generally why you derived in the first place). I believe you could derive
from the pseudo-covariant class if you didn't try to override any
pseudo-covariant functions.
If you try to override the generic version of the function, you'll get this
error:
C2555: 'Derived::Clone': overriding virtual function return type differs and
is not covariant from 'Base::Clone'.
If you try to override the specific version of the function, you'll instead
get this error:
C2392: 'Base __gc *Derived::Clone(void)' : covariant returns types are not
supported in managed types.
I wouldn't be surprised if the next version of MC++ makes one or the other of
these scenarios work, but that's a ways off from now...
Ken
"Stephen Walch" <sw****@proposion.com> wrote in message
news:uQ**************@TK2MSFTNGP12.phx.gbl... Can you tell me more about this "dirty hack"? I do not minf making my classes final; I just want managed applications that use my library to see the more-derived returned types. Can you give me an example, perhaps based on my original problem. Deriving from:
public abstract interface IDbCommand { public abstract new System.Data.IDbConnection Connection [ get, set ] }
what I want clients to see:
public __gc class MyCommand : public IDbCommand { __property MyConnection* get_Connection(); __property void set_Connection(MyConnection* value); }
You'll have to write the MyCommand class in C#. Then you can do:
public class MyCommand : IDbCommand {
IDbConnection IDbCommand.Connection {
get {...}
set {...}
}
public MyConnection Connection {
get {...}
set {...}
}
}
This implements the IDbCommand's Connection property, while not exposing it to
users of your class (unless they cast you to your IDbCommand interface).
Then, with the IDbCommand version hidden, you are creating a new property with
your new signature that returns your MyConnection type.
Ken
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:ej**************@TK2MSFTNGP12.phx.gbl... I'm not sure you can do a tear-off interface in Managed C++.
You could sort of simulate a tear-off interface in the CLR by defining an
implicit conversion from your class to the interface which will be torn-off,
and when that implicit conversion occurs, you could create an internal object
that implements the interface and return it.
The wrinkle in that plan is the torn-off interface cannot be casted back to
the original object. Whether or not that is sufficient for what you are
attempting to do is another issue.
Ken
Ken, Well, specifically, you can't override the pseudo-covariant function
(which is generally why you derived in the first place). I believe you could derive from the pseudo-covariant class if you didn't try to override any pseudo-covariant functions.
O.K. so if I'm reading you correctly its the 'same' problem, you can not
make the derived functions type more specific then the base functions type.
In other words Covariant return types are just not supported in any of the
..NET languages. Not sure if IL itself supports it or not. I understand there
is a 'redirection' method that Eiffel uses to achieve it.
What I normally do is meet 'half way', the function in the abstract base
class has a more specific type then the interface, while all the functions
in the derived classes have the same return type as the abstract base class
function.
Thanks for the info
Jay
"Ken Alverson" <US********@Alverson.net> wrote in message
news:uJ**************@TK2MSFTNGP09.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in
message news:OA****************@tk2msftngp13.phx.gbl... Ken, your class will become unusable as a base class for Managed C++ users. Will Managed C++ have the same issue with VB.NET classes that make the implementing function private? I know at the IL level the C# & VB.NET technique are slightly different, while having the same net effect.
I honestly don't know, but I would suspect the effect would be the same.
Out of curiosity why is it that Managed C++ cannot derive from them? I realize that the method of the interface itself is now hidden, I would
not expect that to preclude you from inheriting from it.
Well, specifically, you can't override the pseudo-covariant function
(which is generally why you derived in the first place). I believe you could derive from the pseudo-covariant class if you didn't try to override any pseudo-covariant functions.
If you try to override the generic version of the function, you'll get
this error:
C2555: 'Derived::Clone': overriding virtual function return type differs
and is not covariant from 'Base::Clone'.
If you try to override the specific version of the function, you'll
instead get this error:
C2392: 'Base __gc *Derived::Clone(void)' : covariant returns types are
not supported in managed types.
I wouldn't be surprised if the next version of MC++ makes one or the other
of these scenarios work, but that's a ways off from now...
Ken
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:OF**************@TK2MSFTNGP10.phx.gbl... O.K. so if I'm reading you correctly its the 'same' problem, you can not make the derived functions type more specific then the base functions type. In other words Covariant return types are just not supported in any of the .NET languages. Not sure if IL itself supports it or not. I understand there is a 'redirection' method that Eiffel uses to achieve it.
Almost, but it's worse than that.
If your base class uses explicit interface implementation to simulate
covariant return, you *can not* override that function in Managed C++. I'm
not saying you can't override it covariantly, you can't override at all. If
you try to override it covariantly, you get a message saying covariant return
isn't supported on managed types. If you try to override it non-covariantly,
you get a message complaining that your return type was contravariant from the
return type of your pseudo-covariant parent.
It's a catch-22.
Ken
Ken, If your base class uses explicit interface implementation to simulate covariant return, you *can not* override that function in Managed C++.
I get it, it does sound like a bug in the way Managed C++ is interpreting
the base class from C#.
As I don't have a problem from C#, or in VB.NET when I use the VB.NET
method.
I wonder if Whidbey is going to offer anything for this.
Thanks for the info
Jay
"Ken Alverson" <US********@Alverson.net> wrote in message
news:Oc*************@TK2MSFTNGP10.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in
message news:OF**************@TK2MSFTNGP10.phx.gbl... O.K. so if I'm reading you correctly its the 'same' problem, you can not make the derived functions type more specific then the base functions
type. In other words Covariant return types are just not supported in any of
the .NET languages. Not sure if IL itself supports it or not. I understand
there is a 'redirection' method that Eiffel uses to achieve it. Almost, but it's worse than that.
If your base class uses explicit interface implementation to simulate covariant return, you *can not* override that function in Managed C++.
I'm not saying you can't override it covariantly, you can't override at all.
If you try to override it covariantly, you get a message saying covariant
return isn't supported on managed types. If you try to override it
non-covariantly, you get a message complaining that your return type was contravariant from
the return type of your pseudo-covariant parent.
It's a catch-22.
Ken
Yes, C++ in Whidbey is going to support the CLR feature of explicit
interface implementations. Current plan is to offer the fully general
functionality of VB in that respect (but we think with nicer syntax).
Ronald Laeremans
Visual C++ team
"Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message
news:uT**************@TK2MSFTNGP09.phx.gbl... Ken, If your base class uses explicit interface implementation to simulate covariant return, you *can not* override that function in Managed C++. I get it, it does sound like a bug in the way Managed C++ is interpreting the base class from C#.
As I don't have a problem from C#, or in VB.NET when I use the VB.NET method.
I wonder if Whidbey is going to offer anything for this.
Thanks for the info Jay
"Ken Alverson" <US********@Alverson.net> wrote in message news:Oc*************@TK2MSFTNGP10.phx.gbl... "Jay B. Harlow [MVP - Outlook]" <Ja********@email.msn.com> wrote in message news:OF**************@TK2MSFTNGP10.phx.gbl... O.K. so if I'm reading you correctly its the 'same' problem, you can
not make the derived functions type more specific then the base functions type. In other words Covariant return types are just not supported in any of the .NET languages. Not sure if IL itself supports it or not. I understand there is a 'redirection' method that Eiffel uses to achieve it.
Almost, but it's worse than that.
If your base class uses explicit interface implementation to simulate covariant return, you *can not* override that function in Managed C++. I'm not saying you can't override it covariantly, you can't override at all. If you try to override it covariantly, you get a message saying covariant return isn't supported on managed types. If you try to override it non-covariantly, you get a message complaining that your return type was contravariant
from the return type of your pseudo-covariant parent.
It's a catch-22.
Ken
It worked! I had to play around with it a bit to find the right C++
syntax. Here is what I ended up with:
private:
IDbConnection* IDbCommand::get_Connection();
void IDbCommand::set_Connection(IDbConnection* value);
public:
[ MyAttributes ]
__property MyConnection* get_Connection();
__property void set_Connection(MyConnection* value);
Note that I had to remove "__property" from the interface implementations. I
could compile with them there, by client C# code complained that they could
not access the property.
Thanks for the support. You saved me from having to implement a complete
set of C# wrapper classes as my public interface!
-Steve
----- Original Message -----
From: "Ken Alverson" <US********@Alverson.net>
Newsgroups: microsoft.public.dotnet.languages.vc
Sent: Thursday, October 23, 2003 4:54 PM
Subject: Re: What can I do about Covariant return types? "Stephen Walch" <sw****@proposion.com> wrote in message news:uQ**************@TK2MSFTNGP12.phx.gbl... Can you tell me more about this "dirty hack"? I do not minf making my classes final; I just want managed applications that use my library to
see the more-derived returned types. Can you give me an example, perhaps
based on my original problem. Deriving from:
public abstract interface IDbCommand { public abstract new System.Data.IDbConnection Connection [ get,
set ] }
what I want clients to see:
public __gc class MyCommand : public IDbCommand { __property MyConnection* get_Connection(); __property void set_Connection(MyConnection* value); } You'll have to write the MyCommand class in C#. Then you can do:
public class MyCommand : IDbCommand { IDbConnection IDbCommand.Connection { get {...} set {...} } public MyConnection Connection { get {...} set {...} } }
This implements the IDbCommand's Connection property, while not exposing
it to users of your class (unless they cast you to your IDbCommand interface). Then, with the IDbCommand version hidden, you are creating a new property
with your new signature that returns your MyConnection type.
Ken
This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Tydr Schnubbis |
last post by:
I've read an interview with Brian Kernighan here:
http://www-2.cs.cmu.edu/~mihaib/kernighan-interview/index.html.
The interviewer asks him, among other things, about the weaknesses of C.
This is...
|
by: Stefan Slapeta |
last post by:
Hi,
this code does not compile in C#:
class base_class {}
class derived_class : base_class {}
class A
{
public virtual base_class f()
|
by: Mike |
last post by:
I keep running into the scenario below over and over again. Currently I get
around not having covariant return types by using an interface and explicit
property definitions which works to some...
|
by: Bob Hairgrove |
last post by:
Consider the classic clone() function:
class A {
public:
virtual ~A() {}
virtual A* clone() const = 0;
};
class B : public A {
public:
|
by: hammad.awan_nospam |
last post by:
Hello,
I'm wondering if it's possible to do the following with Generics:
Let's say I have a generic member variable as part of a generic class
like this:
List<DLinqQuery<TDataContext>>...
|
by: Alex Vinokur |
last post by:
Here is a code from
http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8
--------------------------------------
class Shape {
public:
virtual ~Shape() { } // A...
|
by: kikazaru |
last post by:
Is it possible to return covariant types for virtual methods inherited
from a base class using virtual inheritance?
I've constructed an example below, which has the following structure:
Shape...
|
by: Rahul |
last post by:
Hi Everyone,
I was trying to implement covariant return types and i get a
compilation error,
class BB : public AA
{
};
class A
|
by: Rina0 |
last post by:
Cybersecurity engineering is a specialized field that focuses on the design, development, and implementation of systems, processes, and technologies that protect against cyber threats and...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 2 August 2023 starting at 18:00 UK time (6PM UTC+1) and finishing at about 19:15 (7.15PM)
The start time is equivalent to 19:00 (7PM) in Central...
|
by: linyimin |
last post by:
Spring Startup Analyzer generates an interactive Spring application startup report that lets you understand what contributes to the application startup time and helps to optimize it. Support for...
|
by: erikbower65 |
last post by:
Here's a concise step-by-step guide for manually installing IntelliJ IDEA:
1. Download: Visit the official JetBrains website and download the IntelliJ IDEA Community or Ultimate edition based on...
|
by: kcodez |
last post by:
As a H5 game development enthusiast, I recently wrote a very interesting little game - Toy Claw ((http://claw.kjeek.com/))。Here I will summarize and share the development experience here, and hope it...
|
by: Taofi |
last post by:
I try to insert a new record but the error message says the number of query names and destination fields are not the same
This are my field names
ID, Budgeted, Actual, Status and Differences
...
|
by: Rina0 |
last post by:
I am looking for a Python code to find the longest common subsequence of two strings. I found this blog post that describes the length of longest common subsequence problem and provides a solution in...
|
by: lllomh |
last post by:
Define the method first
this.state = {
buttonBackgroundColor: 'green',
isBlinking: false, // A new status is added to identify whether the button is blinking or not
}
autoStart=()=>{
|
by: DJRhino |
last post by:
Was curious if anyone else was having this same issue or not....
I was just Up/Down graded to windows 11 and now my access combo boxes are not acting right. With win 10 I could start typing...
| |