473,511 Members | 15,302 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

What can I do about Covariant return types?

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
Nov 16 '05 #1
13 4237
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

Nov 16 '05 #2
"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
Nov 16 '05 #3
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

Nov 16 '05 #4
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

Nov 16 '05 #5
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


Nov 16 '05 #6
"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
Nov 16 '05 #7
"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
Nov 16 '05 #8
"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
Nov 16 '05 #9
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

Nov 16 '05 #10
"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
Nov 16 '05 #11
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

Nov 16 '05 #12
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


Nov 16 '05 #13
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

Nov 16 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
2838
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...
14
1988
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()
2
1469
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...
16
3178
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:
11
2451
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>>...
8
2166
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...
3
4533
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...
9
1861
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
0
7371
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
7093
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
7517
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
5676
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
5077
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
3230
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...
0
3218
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
1583
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
1
791
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.