eldiener

I have an interface with static operators like below:

public interface class IA
{
static operator int (IA ^ parm); // convert to int
static operator IA ^ (int i); // convert from int
static IA ^ operator * (IA ^ parm); // dereference returning self, gives error ( see below )
// some instance functions which are used by the first two static operators
IA ^ ReturnSelf(); // called by third static operator to return self on dereference
};

I have a ref class, called X, which implements the interface and defines the instance functions, like this:

public ref class X : IA
{
// implementation of IA's instance functions
IA ^ ReturnSelf() { return this };
};

I test X's implementation with code like this:

X ^ x = gcnew X;
IA ^ ix = safe_cast<IA ^>(x);
int ii = 0;
ii = *x; // this works fine
*x = 8; // this gives error C2106: '=' : left operand must be l-value

Does anybody have any idea why the interface's dereference operator is not producing an lvalue I admit that dereferencing to oneself is unusual, but surely a ref class object is an lvalue.








Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

einaros

eldiener wrote:

static operator IA ^ (int i); // convert from int

You should implement an assignment operator or constructor to "convert from int". The above operator won't do you much good.






Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

eldiener

einaros wrote:

eldiener wrote:

static operator IA ^ (int i); // convert from int

You should implement an assignment operator or constructor to "convert from int". The above operator won't do you much good.



In C++/CLI an assignment operator is not CLS-compliant. Please read the section 19.7.5.3 called "Assignment Operators" in the "C++/CLI Language Specification, 1st Edition December 2005".

Please look at my post at http://forums.microsoft.com/MSDN/ShowPost.aspx PostID=1422410&SiteID=1 and the answer given by Rob Teixeira.

According to the MSDN documentation, for the topic "Convert-From Operators" in the "C++ Language Reference":

Convert-from operators:

  • Shall be defined as static functions.

  • Can either be implicit (for conversions that do not lose precision such as short-to-int) or explicit, when there may be a loss of precision.

  • Shall return an object of the containing class.

  • Shall have the "from" type as the sole parameter type.

In my case I am coding an implicit convert-from operator.

So I do not understand at all your remark that "The above operator won't do much good." In fact the above operator is the only one that is CLS-compliant. Also, of course no constructor can exist in an interface but that is irrelevant considering that the CLS way of doing an assignment operator is via a static Convert-From operator according to the documentation..

So I still do not understand the error message.





Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

einaros

eldiener wrote:

So I do not understand at all your remark that "The above operator won't do much good."

I'll admit right away that native C++ is my strength, not the oddities of C++/CLI, so that was perhaps an unfit assumption Smile

I'm heading offline right now, so I can't follow up on the issue for some time. Hopefully someone with more CLI insight will pick up on the post while I'm gone. If not, I'll look into the matter when I return.






Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

eldiener

einaros wrote:

eldiener wrote:

So I do not understand at all your remark that "The above operator won't do much good."

I'll admit right away that native C++ is my strength, not the oddities of C++/CLI, so that was perhaps an unfit assumption

I'm heading offline right now, so I can't follow up on the issue for some time. Hopefully someone with more CLI insight will pick up on the post while I'm gone. If not, I'll look into the matter when I return.



While I always appreciate your help, no further answer has been given, and your answer was not relevant. Hopefully someone else will address this issue, else I will repost under another slightly different topic.




Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

Brian Kramer

I tried to help also, but cannot explain the L-value problem. I would open a bug with a simplified version of the code.

I don't see how the discussion of whether operator= is CLS compliant is related to this issue.





Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

eldiener

Brian Kramer wrote:

I tried to help also, but cannot explain the L-value problem. I would open a bug with a simplified version of the code.

I don't see how the discussion of whether operator= is CLS compliant is related to this issue.



The only reason why I mentioned that the C++/CLI operator = is not CLS compliant is to defend my using of the implicit convert-from syntax which emulates operator = in a CLS compliant way in dot-net. The use of the convert-from syntax is needed in the line:

Code Snippet

*x = 8; // this gives error C2106: '=' : left operand must be l-value


where after the dereferenced operator, whch does not work and is the issue of the OP, the assignment operator should be calling the convert-from syntax to convert an int to the class type.

I will work on a bug report and submit it. After I do I will post the URL of the bug report as a follow up message. I already anticipate that the response from the bug report will tell me that I can not use the dereference operator in the way that I do, although I can find no documentation on any limitation of how one chooses to use the CLS-compliant operators in dot-net. But I will see after I post the bug report.





Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

Shakje

Before I start, I am not incredibly experienced in CLI, so don't have a go at me if I say something stupid.

What I wanted to say was essentially, why are you creating what looks like an operator that converts an int to an IA handle Why don't you just convert to a plain IA object Have you tried this

What it seems you're doing is getting the this pointer..

So what's happening is that ii is storing the address of x in it which is why it works, but you can't store 8 in a this pointer.

Try:

IA ^ ReturnSelf() { return *this };

maybe

Also you're converting an int to an IA handle, why not a reference And converting from a handle to an int.

I would have thought that you should be doing the above to return the object itself, then using an operator on an IA object instead to handle conversions.




Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

Brian Kramer

Shakje wrote:

So what's happening is that ii is storing the address of x in it which is why it works, but you can't store 8 in a this pointer.

No. The conversion operator from X^ to int is invoked. *x is not the address of x, but rather whatever X :: operator * (dereference operator) returns. It is not possible to get an address of a managed instance such as x, which is the point of managed code.

Storing 8 in this pointer is not what this code is trying to do. It is trying to use the conversion operator from int to X^.

The point of this thread is that he defines a dereference operator that returns X^, but cannot use the int to X^ operator.

eldiener: it is becoming clearer to me that this is by design. It seems intuitive that an expression that evaluates to a handle cannot made to point to a new instance, so functions that return references are not returning L-values. It would take a C++/CLI language lawyer to nail down why this would be the case.

How about if you instead defined you dereference operator to use tracking references. Intuitively this should work. Indeed, it does compile on my machine (but I get other link errors in my version)

static X% operator *( X% x ) // dereference operator

{

return x;

}





Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

eldiener

Shakje wrote:

Before I start, I am not incredibly experienced in CLI, so don't have a go at me if I say something stupid.

What I wanted to say was essentially, why are you creating what looks like an operator that converts an int to an IA handle Why don't you just convert to a plain IA object Have you tried this


IA is a C++/CLI reference class. In order to emulate the normal C++ assignment operator in a C++/CLI reference class, one creates a static conversion operator which takes the value one is trying to assign as a single parameter and "returns" the reference class handle.

In standard C++, one would create an assignment operator with a signature of:

SomeClass & operator = (int value);

in C++/CLI, and assignment operator is non-CLS compliant. The CLS-compliant equivalent for a reference class is:

static operator SomeRefClass ^ (int value);

or for a C++/CLI value class:

static operator SomeValueClass (int value);

In C++/CLI this static function is invoked by:

SomeRefClass ^ src(gcnew SomeRefClass);
src = 1; // this invokes the static convert from int operator

or

SomeValueClass svc;
svc = 1; // this invokes the static convert from int operator

The problem in my OP has nothing to do with the static convert from int operator but rather with the static dereference operator. Furthermore I did not show the implementation in class X of this static convert from int operator. The function which I did show in class X, called ReturnSelf(), was used by the dereference operator in my example.

In my example I am showing that the dereference operator is returning the object itself by its handle, which is unusual but certainly does not seem illegal.

Shakje wrote:


What it seems you're doing is getting the this pointer..

So what's happening is that ii is storing the address of x in it which is why it works, but you can't store 8 in a this pointer.

Try:

IA ^ ReturnSelf() { return *this };

maybe

Also you're converting an int to an IA handle, why not a reference And converting from a handle to an int.

I would have thought that you should be doing the above to return the object itself, then using an operator on an IA object instead to handle conversions.


No, you are not understanding that for a C++/CLI reference class static operators operate on an object which is a handle to the class.




Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

Shakje

Thanks Brian, what does 'this' actually return in this case




Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

Shakje

Thanks, very good explanation Smile




Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

Brian Kramer

'this' doesn't "return" anything. It simply is a reference (^) to the instance upon which some class method has been invoked.

e.g.

ref class X
{

void foo() { /* this is type X^ in this scope */ }
};





Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

eldiener

Brian Kramer wrote:
Shakje wrote:

So what's happening is that ii is storing the address of x in it which is why it works, but you can't store 8 in a this pointer.

No. The conversion operator from X^ to int is invoked. *x is not the address of x, but rather whatever X :: operator * (dereference operator) returns. It is not possible to get an address of a managed instance such as x, which is the point of managed code.

Storing 8 in this pointer is not what this code is trying to do. It is trying to use the conversion operator from int to X^.

The point of this thread is that he defines a dereference operator that returns X^, but cannot use the int to X^ operator.

eldiener: it is becoming clearer to me that this is by design. It seems intuitive that an expression that evaluates to a handle cannot made to point to a new instance, so functions that return references are not returning L-values. It would take a C++/CLI language lawyer to nail down why this would be the case.



Whether it points to a new instance or not seems to be irrelevant. Any object that is of type "handle to a ref class" is an l-value.


Brian Kramer wrote:

How about if you instead defined you dereference operator to use tracking references. Intuitively this should work. Indeed, it does compile on my machine (but I get other link errors in my version)

static X% operator *( X% x ) // dereference operator

{

return x;

}



This may be valid but it should operate, I would think, only on an object which is of type X%, not on an object which is of type X^. I believe that if I did not have my own static dereference operator defined, that the built-in dereference would be along the lines of:

static IA% operator * (IA^ x);

In other words, using the built-in C++/CLI dereference, if I had:

IA^ x(gcnew IA);

then:

IA% y(*x);

would be the result, but clearly if I then applied this:

y = 8; // the equivalent of *x = 8; in my originally example

it should not be calling my static operator IA ^ (int i); // convert from int

since I would think that only operates on an object of type IA^ and not on an object of type IA%. The question then is whether a static operator for a ref class operates on an object which is a tracking reference to that class as opposed to a handle to that class I will try this out and see what happens.




Re: Visual C++ Language Interface dereference operator ( * ) implementation not creating LValue

Brian Kramer

eldiner, there seems to be a couple loose ends that will require new involvement. So, I'm leaving it up to you to decide if you want to mark this thread as answered.

Thanks.