473,394 Members | 1,810 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Are conversion operators "illegal" in C++/CLI?

I have some problems using conversion operators in C++/CLI. In my
project I have two ref class:es Signal and SignalMask and I have an
conversion function in Signal to convert Signal:s to SignalMask:s. The
reason is I have a free function called WaitSignal that accepts av
SignalMask where Signals parameters are supposed to implicitly be
converted to SignalMask:s. I'm using the SignalMask class because I
want to be able to supply a logic expression of which signals I want to
listen to at the same time:

WaitSignal(s1 || s2 || s3); // wait for any of the three signals

But to make the function WaitSignal accept a single Signal argument I'm
relying on the conversion operator in the Signal class to convert a
Signal argument to a SignalMask. As in normal C++ this requires a const
reference to work since it's not allowed to call a function with a
non-const temporary object.

That's fine. But the problem is that in C++/CLI you are not allowed to
use a const object in *any* way since you cannot specify which
operations on a class is const and which are not.

So I'm required to supply a const object reference to call the
conversion operator but then I cannot use the object! I'm I missing
something or is this a known problem in C++/CLI?

Note that I'm using the ref classes with stack semantic to
deteministically destruct the objects.

A simple example:
=================

ref class SignalMask;

ref class Signal {
public:
operator SignalMask();
};

ref class SignalMask {
public:
SignalMask(SignalMask% other);

void DoAnything() { }
};

void WaitSignal(const SignalMask% mask)
{
// *any* use of object mask is forbidden
// - even const operations (which you can't specify)
mask.DoAnything();
}

int main()
{
Signal s1;
WaitSignal(s1);

return 0;
}

If I remove the const qualifier in WaitSignal(const SignalMask% mask)
the conversion operator is not invoked and if I keep const I cannot use
the object supplied. Catch 22!

Thanks in advance.

Best Regards,
Påhl

Dec 29 '05 #1
4 2877
"Påhl Melin" <pa********@zenterio.com> wrote

I have some problems using conversion operators in C++/CLI. In my
project I have two ref class:es Signal and SignalMask and I have an
conversion function in Signal to convert Signal:s to SignalMask:s. The
reason is I have a free function called WaitSignal that accepts av
SignalMask where Signals parameters are supposed to implicitly be
converted to SignalMask:s. I'm using the SignalMask class because I
want to be able to supply a logic expression of which signals I want to
listen to at the same time:

WaitSignal(s1 || s2 || s3); // wait for any of the three signals

<hg>
There are probably better ways to achieve what you want, but that
depends on the way these classes are related.
</hg>

But to make the function WaitSignal accept a single Signal argument I'm
relying on the conversion operator in the Signal class to convert a
Signal argument to a SignalMask. As in normal C++ this requires a const
reference to work since it's not allowed to call a function with a
non-const temporary object.

<hg>
I don't quite understand. If both Signal and SignalMask are ref classes
you could return provide a conversion to SignalMask^.
</hg>

That's fine. But the problem is that in C++/CLI you are not allowed to
use a const object in *any* way since you cannot specify which
operations on a class is const and which are not.

<hg>
You can still use cv qualifiers in signatures. Just the member function
qualifiers are not accepted. I believe the reasoning behind it was,
that cv qualified member functions are of little use.
</hg>

So I'm required to supply a const object reference to call the
conversion operator but then I cannot use the object! I'm I missing
something or is this a known problem in C++/CLI?

<hg>
The conversion operator does not need to be const. You would
really need to be able to add a const qualifier to DoAnything.
</hg>

Note that I'm using the ref classes with stack semantic to
deteministically destruct the objects.

<hg>
Ah, I see. In that case you're out of luck, I'm afraid :-(
Standard C++ idioms don't work too great in the managed world.
And as AFAICT it was not considered an important design goal
for the C++/CLI language design.

Anyway, you can always cast constness away with a const_cast.

const_cast<SignalMask%>(mask).DoAnything();

</hg>

-hg
Dec 29 '05 #2
> I'm using the SignalMask class because I want to be able to
supply a logic expression of which signals I want to listen to
at the same time:

WaitSignal(s1 || s2 || s3); // wait for any of the three signals

<hg>
There are probably better ways to achieve what you want, but that
depends on the way these classes are related.
</hg>
Any ideas? I want to be able to extend the idea in the future to allow
any type of logic expression based on which signals have arrived (been
raised) like:

// wait for both signal s1 and s2 to be raised or a timeout signal
WaitSignal(s1 && s2 || timeoutSignal);
<hg>
You can still use cv qualifiers in signatures. Just the member function
qualifiers are not accepted. I believe the reasoning behind it was,
that cv qualified member functions are of little use.
</hg>
Yes, I can use a const qualifier in the function signature (as I did)
but then it's not possible to use the parameter, so there is little
point doing it.

I thought they didn't allow cv qualifiers because the CLR and the other
..net languages doesn't support const at all. But they are *required* if
you want to combine stack semantic with temporary objects, like when
you invoke an implicit conversion operator as I do in my example. To
me, it looks like a clash between ISO C++ and C++/CLR semantics.
Note that I'm using the ref classes with stack semantic to
deterministically destruct the objects.

<hg>
Ah, I see. In that case you're out of luck, I'm afraid :-(
Standard C++ idioms don't work too great in the managed world.
And as AFAICT it was not considered an important design goal
for the C++/CLI language design.
I probably got carried away by the praise Microsoft and Herb Sutter
gives to themselves for allowing the classic RAII idiom in C++/CLI. It
sounded like you could use the ISO C++ stack semantic for all ref
classes in C++/CLI. But they list a few classes in the help files that
doesn't support stack semantic, like System:String.

The problem IMHO is that when you almost implement a new feature it
creates uncertainty about when to use is at all if it just works in
*some* cases and the code gets confusing when you are combining
different techniques for the same problem in the same function or
module (having some stack objects and some gc objects in the same
function - it hard to understand the motive by e.g. a maintenance
programmer looking through the code later on).

But still, I totally agree on the value of having deterministic
destructors so I would like to use it as much as possible. I just have
to learn when it works and when it doesn't work.
Anyway, you can always cast constness away with a const_cast.

const_cast<SignalMask%>(mask).DoAnything();


Hadn't thought about that. But IMHO this is really ugly and is only a
last resort (mostly a work-around when mutable haven't been used). It
shouldn't be done in a standard solution like just getting the
conversion operator work. I would prefer another solution, if possible.

One way to solve it, I presume, would be to make the SignalMask class
non-managed (a normal class). Or to supply an extra overload of the
WaitSignal() function that takes a single Signal% parameter and creates
a non-temporary SignalMask object and calls the "real" WaitSignal()
function.

Dec 29 '05 #3
"Påhl Melin" <pa********@zenterio.com> wrote
There are probably better ways to achieve what you want, but that
depends on the way these classes are related.
</hg>


Any ideas? I want to be able to extend the idea in the future to allow
any type of logic expression based on which signals have arrived (been
raised) like:

// wait for both signal s1 and s2 to be raised or a timeout signal
WaitSignal(s1 && s2 || timeoutSignal);

You could use a common base (or interface) for your classes.
You may also want to use some expression template techniques
(creating class template wrappers for the above expressions
and deferring the evaluation to a later point in time)

Oc, you could also add cleanup handling to the WaitSignal
implementation or use native classes for the wrappers.
Note that I'm using the ref classes with stack semantic to
deterministically destruct the objects.

<hg>
Ah, I see. In that case you're out of luck, I'm afraid :-(
Standard C++ idioms don't work too great in the managed world.
And as AFAICT it was not considered an important design goal
for the C++/CLI language design.


I probably got carried away by the praise Microsoft and Herb Sutter
gives to themselves for allowing the classic RAII idiom in C++/CLI. It
sounded like you could use the ISO C++ stack semantic for all ref
classes in C++/CLI. But they list a few classes in the help files that
doesn't support stack semantic, like System:String.

There are indeed things in the language design which make me
shake my head in disbelief. That said, we can still hope that
C++/CLI will evolve faster than ISO C++ and that some of the
issues will be fixed. But I guess, that would require someone of the
Softies to grasp it :-O

-hg
Dec 29 '05 #4
Påhl Melin wrote:
If I remove the const qualifier in WaitSignal(const SignalMask% mask)
the conversion operator is not invoked and if I keep const I cannot use
the object supplied. Catch 22!


That's an interesting observation. You're out of luck here, because the
..NET framework doesn't support the concept of const member functions.
You really shouldn't use the const keyword anywhere, you'll just get
into trouble with that, as you won't be able to call any of the member
functions of a const object (and the const_cast hack is not worth it, in
my opinion, unless you absolutely have no other choice).

In ISO C++ the conversion operator works when you pass by value or by
const reference. In C++/CLI you can't pass a ref class by value and
can't pass it by const reference either (in a meaningful way), so you're
out of luck. From your example it seems to me that conversion operators
make little sence with ref classes, as there's not a signle practical
case in which they would be called automatically. As Holger said, not
all ISO C++ idioms work well in .NET.

Even in ISO C++, I would question the conversion operator in this case.
It may be dangerous, as you could accidentally convert a Signal to
SignalMask, without even a warning. I tend not to define conversion
operators unless the two types are completely interchangeable without
significant loss of data. But that's a different topic.

Tom
Jan 2 '06 #5

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

Similar topics

2
by: Kostatus | last post by:
The following code worked perfectly fine until i modified an unrelated part of the program: this->dungArea.mBlocked = mioS.mio_dungArea.mFlags & isBlocked; after that i started getting the...
2
by: qe_Cui | last post by:
Hello everyone: I am using vb.net 2003, sqlserver2000 database, and windows 2000 professional OS. In the program, I encrypt the login user's userid and passed with RSACryptoServiceProvider....
2
by: Karl Koscher | last post by:
I'm trying to communicate with a USB device using C#. I'm able to determine the device path using P/Invoke and SetupDiGetClassDevs, SetupDiEnumDeviceInterfaces, and SetupDiGetDeviceInterfaceDetail,...
4
by: Ondrej Spanel | last post by:
The code below does not compile with .NET 2003, I get folowing error: w:\c\Pokusy\delegTemplArg\delegTemplArg.cpp(11) : error C2993: 'float' : illegal type for non-type template parameter 'x' ...
1
by: Steve Grahovac | last post by:
I have been having trouble the last few days opening any ASP.NET web forms in the design view in the designer. Every time I clicked on an aspx file I got a message box with the error "Unable to...
0
by: qe_Cui | last post by:
Hello everyone: I am using vb.net 2003, sqlserver2000 database, and windows 2000 professional OS. In the program, I encrypt the login user's userid(is "sa") and passed(is "sa") with...
0
by: Felix Finch | last post by:
I have a perl test program which has about 80 test cases, each of which creates its own schema so I can remove them with DROP SCHEMA xxx CASCADE. Normally each test case creates and drops the same...
3
by: Eckhard Schwabe | last post by:
I only found one post on Google where someone mentions the same problem with a DataSet: XmlDataReader in .Net 1.1 can not read XML files from a path which contains "%10" or "%3f". code to...
1
by: Shilpa | last post by:
Hi, I have a OpenFileDialog on my windows form whose filter is *.*. I want the users to be able to further filter the files by giving *.doc or *.zip etc in the "file name" field of the dialog...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
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,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
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
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...

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.