I think this is a bug...

P

Peter Oliphant

Here is a case where something that shouldn't compile does. Note below that
Test_Method() only accepts a pointer to Test_Struct as an parameter, but it
will compile with a value instance as a parameter.

For context, I'm using VS C++.NEW 2005 Express with clr:/pure syntax. I
submitted this as a bug report, link below:

http://lab.msdn.microsoft.com/produ...edbackid=ef3c8d9e-75e2-4916-87ee-640a4de75f39

Source below:

// Test_Compiler.cpp : main project file.

#include "stdafx.h"

using namespace System;

value struct Test_Struct
{
long x ;
} ;

ref class My_Class
{
public:

My_Class() {}
~My_Class() {}

private:

void Test_Compiler()
{
Test_Struct info ;

Test_Method( info ) ; // shouldn't compile, but does!!!
Test_Method( %info ) ; // ok
}

void Test_Method( Test_Struct^ info ) {}
} ;

int main(array<System::String ^> ^args)
{
return 0 ;
}

[==P==]
 
H

Holger Grund

Peter Oliphant said:
value struct Test_Struct
{
long x ;
} ;
[..]
Test_Struct info ;

Test_Method( info ) ; // shouldn't compile, but does!!!
Test_Method( %info ) ; // ok
}

void Test_Method( Test_Struct^ info ) {}
} ;
I think it's feature. That's "implicit boxing". There's
a boxing conversion from every V to V^ to support
certain types of polymorphism.

For instance, you couldn't write
Console::WriteLine( info );
without it.

You can think of every Value type having a magic
member
value struct V { V^ operator() const; };

Now there's a conversion sequence from gclvalue V
to Object^ via the boxing conversion followed by
the base class handle conversion.

-hg
 
P

Peter Oliphant

Ok, I'll buy that. Sort of. BUT --- doesn't this feature reverse the concept
of type-checking? One of the reasons for passing something by value is so
the original can't be changed. Doesn't this feature violate that concept?

In my example code, the call Test_Method(info) looks like it will pass a
value. But Test_Method is passed a pointer, so it can validly be written
with changing what it is passed as a legal method. For example:

void Test_Method( Test_Struct^ info )
{
info->x = 1 ;
}

I just tried this, and if passed the value the code doesn't change the value
of 'x', but if passed a pointer it does. This caused me a half-day of
looking at the code, since I saw the value change in the method and assumed
it remained changed outside the method. But when I finally looked at 'info'
outside the call it had changed, at which point I realized I had forgotten
the '%' and was passing the value instead of the pointer.

AT THE VERY LEAST THIS SHOULD GENERATE A LOW-LEVEL WARNING.

This also brings up the concept that If I HAD overloaded Test_Method() with
a version that DID take a value instead of a pointer, note that my code
would start executing in this new version all of a sudden. So code that
'worked' because it was incorrectly going to a method assuming a pointer now
goes to the new one made for a value type, and the code stops working for
reasons that seem bizarre. And now one must look at code that has not been
changed but is reacting differently since some of the calls it it have been
're-routed' without any warning.

These scenario's couldn't happen if this flagged an error (or a warning)
instead of being a feature...

[==P==]

Holger Grund said:
Peter Oliphant said:
value struct Test_Struct
{
long x ;
} ;
[..]
Test_Struct info ;

Test_Method( info ) ; // shouldn't compile, but does!!!
Test_Method( %info ) ; // ok
}

void Test_Method( Test_Struct^ info ) {}
} ;
I think it's feature. That's "implicit boxing". There's
a boxing conversion from every V to V^ to support
certain types of polymorphism.

For instance, you couldn't write
Console::WriteLine( info );
without it.

You can think of every Value type having a magic
member
value struct V { V^ operator() const; };

Now there's a conversion sequence from gclvalue V
to Object^ via the boxing conversion followed by
the base class handle conversion.

-hg
 
H

Holger Grund

Peter Oliphant said:
Ok, I'll buy that. Sort of. BUT --- doesn't this feature reverse the
concept of type-checking? One of the reasons for passing something by
value is so the original can't be changed. Doesn't this feature violate
that concept?
Not necessarily. You really can't tell whether the value is copied
only from the expression at the call site.

For instance, if the declaration was
void Test_Method( Test_Struct% info);
there wouldn't be a copy involved.

Nonetheless, I agree implicit boxing is dangerous and it
shouldn't be in the language IMHO. But I'm afraid you need
to convince someone else.

FWIW, I use a helper function box or box_cast to do an
explicit cast.

-hg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top