View mode: basic / threaded / horizontal-split · Log in · Help
March 02, 2008
opMul
Is there a reason why opMul cannot be called on a constant object?

This restriction is hardcoded (I clearly don't have a choice for my object).
March 03, 2008
Re: opMul
On Sun, 02 Mar 2008 20:10:23 +0100, Denton Cockburn <diboss@hotmail.com>  
wrote:

> Is there a reason why opMul cannot be called on a constant object?
>
> This restriction is hardcoded (I clearly don't have a choice for my  
> object).


That would be due to opMul not being defined as a const function.


import std.stdio;

struct Foo1
{
	int bar;
	
	Foo1 opMul(int rhs)
	{
		bar *= rhs;
		return *this;
	}
}

struct Foo2
{
	int bar;
	
	Foo2 opMul(int rhs) const // difference here
	{
		bar *= rhs;
		return *this;
	}
}

void main()
{
	const Foo1 foo1 = Foo1(4);
	Foo1 bar1 = foo1 * 3;	// fails

	const Foo2 foo2 = Foo2(4);
	Foo2 bar2 = foo2 * 3;	// works
}
March 03, 2008
Re: opMul
Simen Kjaeraas wrote:
> On Sun, 02 Mar 2008 20:10:23 +0100, Denton Cockburn <diboss@hotmail.com> 
> wrote:
> 
>> Is there a reason why opMul cannot be called on a constant object?
>>
>> This restriction is hardcoded (I clearly don't have a choice for my 
>> object).
> 
> 
> That would be due to opMul not being defined as a const function.
> 
> 
> import std.stdio;
> 
> struct Foo1
> {
>     int bar;
>     
>     Foo1 opMul(int rhs)
>     {
>         bar *= rhs;
>         return *this;
>     }
> }
> 
> struct Foo2
> {
>     int bar;
>     
>     Foo2 opMul(int rhs) const // difference here
>     {
>         bar *= rhs;
>         return *this;
>     }
> }

I can't keep up here.  Is a trailing 'const' legal D syntax now?

--bb
March 03, 2008
Re: opMul
On Mon, 03 Mar 2008 01:47:33 +0100, Simen Kjaeraas wrote:

> On Sun, 02 Mar 2008 20:10:23 +0100, Denton Cockburn <diboss@hotmail.com>  
> wrote:
> 
>> Is there a reason why opMul cannot be called on a constant object?
>>
>> This restriction is hardcoded (I clearly don't have a choice for my  
>> object).
> 
> 
> That would be due to opMul not being defined as a const function.
> 
> 
> import std.stdio;
> 
> struct Foo1
> {
> 	int bar;
> 	
> 	Foo1 opMul(int rhs)
> 	{
> 		bar *= rhs;
> 		return *this;
> 	}
> }
> 
> struct Foo2
> {
> 	int bar;
> 	
> 	Foo2 opMul(int rhs) const // difference here
> 	{
> 		bar *= rhs;
> 		return *this;
> 	}
> }
> 
> void main()
> {
> 	const Foo1 foo1 = Foo1(4);
> 	Foo1 bar1 = foo1 * 3;	// fails
> 
> 	const Foo2 foo2 = Foo2(4);
> 	Foo2 bar2 = foo2 * 3;	// works
> }

A function does not have to be constant to allow a constant parameter.
It just has to promise not to change the parameter.

I don't understand why opMul would change the parameter, or more
importantly, why it can't be stated that it WONT change the parameter in
any cases.

I think this is related to what Janice spoke about.  The constant changes
that have taken place need to be properly incorporated into the language
and library.  There are a lot of places where constant doesn't work as
would be intuitively expected.
March 03, 2008
Re: opMul
On Mon, 03 Mar 2008 02:01:09 +0100, Bill Baxter  
<dnewsgroup@billbaxter.com> wrote:

> Simen Kjaeraas wrote:
>> On Sun, 02 Mar 2008 20:10:23 +0100, Denton Cockburn  
>> <diboss@hotmail.com> wrote:
>>
>>> Is there a reason why opMul cannot be called on a constant object?
>>>
>>> This restriction is hardcoded (I clearly don't have a choice for my  
>>> object).
>>   That would be due to opMul not being defined as a const function.
>>   import std.stdio;
>>  struct Foo1
>> {
>>     int bar;
>>         Foo1 opMul(int rhs)
>>     {
>>         bar *= rhs;
>>         return *this;
>>     }
>> }
>>  struct Foo2
>> {
>>     int bar;
>>         Foo2 opMul(int rhs) const // difference here
>>     {
>>         bar *= rhs;
>>         return *this;
>>     }
>> }
>
> I can't keep up here.  Is a trailing 'const' legal D syntax now?
>
> --bb

Well, in a way. After becoming sober, I re-read this today and... ouch.

It seems to me that the trailing const says "this function is const,  
really!" while in fact, it is not. Case in point: above code, which  
obviously changes this.bar.

Walter (or anyone else who understands const), is this how things are  
supposed to be?

correct code would be as follows:

import std.stdio;

struct Foo1
{
	int bar;
	
	Foo1 opMul(int rhs)
	{
		Foo1 tmp;
		tmp.bar = bar * rhs;
		return tmp;
	}
}

struct Foo2
{
	int bar;
	
	const Foo2 opMul(int rhs) // difference here
	{
		Foo2 tmp;
		tmp.bar = bar * rhs;
		return tmp;
	}
}

void main()
{
	const Foo1 foo1 = Foo1(4);
	Foo1 bar1 = foo1 * 3;	// fails

	const Foo2 foo2 = Foo2(4);
	Foo2 bar2 = foo2 * 3;	// works
}


This correctly fails if this.bar is changed.
March 03, 2008
Re: opMul
On Mon, 03 Mar 2008 04:10:36 +0100, Denton Cockburn <diboss@hotmail.com>  
wrote:
> A function does not have to be constant to allow a constant parameter.
> It just has to promise not to change the parameter.

And that is exactly what const does.

> I don't understand why opMul would change the parameter, or more
> importantly, why it can't be stated that it WONT change the parameter in
> any cases.

Given

struct Foo
{
	int bar;
	void doStuff(Foo b)
	{
		bar += b.bar;
	}
}

would you expect

const Foo f,g;
f.doStuff(g);

to work without problems? This is exactly the same, only doStuff is not  
considered special by the compiler.

You might argue that the compiler should enforce opMul, opDiv, etc. to be  
const, but that does carry a load of other troubles with it.

> I think this is related to what Janice spoke about.  The constant changes
> that have taken place need to be properly incorporated into the language
> and library.  There are a lot of places where constant doesn't work as
> would be intuitively expected.

This is intuitive to me. (Well, apart from what I mentioned in the  
response to Bill :p)
March 03, 2008
Re: opMul
On Mon, 03 Mar 2008 15:08:55 +0100, Simen Kjaeraas wrote:

> On Mon, 03 Mar 2008 04:10:36 +0100, Denton Cockburn <diboss@hotmail.com>  
> wrote:
>> A function does not have to be constant to allow a constant parameter.
>> It just has to promise not to change the parameter.
> 
> And that is exactly what const does.
> 
>> I don't understand why opMul would change the parameter, or more
>> importantly, why it can't be stated that it WONT change the parameter in
>> any cases.
> 
> Given
> 
> struct Foo
> {
> 	int bar;
> 	void doStuff(Foo b)
> 	{
> 		bar += b.bar;
> 	}
> }
> 
> would you expect
> 
> const Foo f,g;
> f.doStuff(g);
> 
> to work without problems? This is exactly the same, only doStuff is not  
> considered special by the compiler.
> 
> You might argue that the compiler should enforce opMul, opDiv, etc. to be  
> const, but that does carry a load of other troubles with it.
> 
>> I think this is related to what Janice spoke about.  The constant changes
>> that have taken place need to be properly incorporated into the language
>> and library.  There are a lot of places where constant doesn't work as
>> would be intuitively expected.
> 
> This is intuitive to me. (Well, apart from what I mentioned in the  
> response to Bill :p)

You are unfortunately completely missing my point.
In the example you give, you don't want a const parameter, because you
change the object.

I WANT a const parameter, because I have NO INTENTION of changing the
parameter.

so what I want is this:

struct Foo
{
	int bar;
	void doStuff(const Foo b)
	{
		bar += b.bar; /* I want an error here */
	}

	/* now more specifically, I want to do the same as above...but with */
	/* opMul */

	Foo opMul(const Foo b)
	{
		Foo res;
		res.bar = bar * b.bar;

		return res;
	}
}

See, I make NO changes to the object in that opMul, so my question
is...why is that illegal (intuitively)?
March 03, 2008
Re: opMul
Denton Cockburn wrote:
> On Mon, 03 Mar 2008 15:08:55 +0100, Simen Kjaeraas wrote:
> 
>> On Mon, 03 Mar 2008 04:10:36 +0100, Denton Cockburn <diboss@hotmail.com>  
>> wrote:
>>> A function does not have to be constant to allow a constant parameter.
>>> It just has to promise not to change the parameter.
>> And that is exactly what const does.
>>
>>> I don't understand why opMul would change the parameter, or more
>>> importantly, why it can't be stated that it WONT change the parameter in
>>> any cases.
>> Given
>>
>> struct Foo
>> {
>> 	int bar;
>> 	void doStuff(Foo b)
>> 	{
>> 		bar += b.bar;
>> 	}
>> }
>>
>> would you expect
>>
>> const Foo f,g;
>> f.doStuff(g);
>>
>> to work without problems? This is exactly the same, only doStuff is not  
>> considered special by the compiler.
>>
>> You might argue that the compiler should enforce opMul, opDiv, etc. to be  
>> const, but that does carry a load of other troubles with it.
>>
>>> I think this is related to what Janice spoke about.  The constant changes
>>> that have taken place need to be properly incorporated into the language
>>> and library.  There are a lot of places where constant doesn't work as
>>> would be intuitively expected.
>> This is intuitive to me. (Well, apart from what I mentioned in the  
>> response to Bill :p)
> 
> You are unfortunately completely missing my point.
> In the example you give, you don't want a const parameter, because you
> change the object.
> 
> I WANT a const parameter, because I have NO INTENTION of changing the
> parameter.
> 
> so what I want is this:
> 
> struct Foo
>  {
>  	int bar;
>  	void doStuff(const Foo b)
>  	{
>  		bar += b.bar; /* I want an error here */
>  	}

You're not changing b, so you're not going to get an error there.

> 	/* now more specifically, I want to do the same as above...but with */
> 	/* opMul */
> 
> 	Foo opMul(const Foo b)
> 	{
> 		Foo res;
> 		res.bar = bar * b.bar;
> 
> 		return res;
> 	}
>  }
> 
> See, I make NO changes to the object in that opMul, so my question
> is...why is that illegal (intuitively)?

Your question is contradictory.  Above you say you want an error, but 
then ask why is that illegal.  It's not illegal.  It works fine.  Did 
you mean "why is it *legal*?"

If you mean why is it *legal* to use a const parameter like that, the 
answer is because const only says you won't change the parameter. 
Merely accessing a value does not change it.

--bb
March 03, 2008
Re: opMul
On Tue, 04 Mar 2008 05:56:57 +0900, Bill Baxter wrote:

> Denton Cockburn wrote:

>> 
>> so what I want is this:
>> 
>> struct Foo
>>  {
>>  	int bar;
>>  	void doStuff(const Foo b)
>>  	{
>>  		bar += b.bar; /* I want an error here */
>>  	}
> 
> You're not changing b, so you're not going to get an error there.

You're right, that was a mistake.

I misphrased my whole query (I misread the compiler error message).
The concern is still there though, here's a sample of code that produces
the message.

struct Foo
{
	int x;
	
	Foo opMul(const Foo b)
	{
		Foo f;
		f.x = x * b.x;
		
		return f;
	}
}

void main()
{
	Foo f;
	Foo y;
	f.x = 6;
	y.x = 7;
	
	const(Foo) t = f;
	Foo p = t * y;
}

produces this error:
test.d(24): function test.Foo.opMul (const(Foo)) does not match parameter types (Foo)
test.d(24): Error: t.opMul can only be called on a mutable object, not const(Foo)


So my question SHOULD have been:

Why can't opMul et al be called on a constant object (reference)?

Sorry for the previous confusion.
March 03, 2008
Re: opMul
Denton Cockburn wrote:
> On Tue, 04 Mar 2008 05:56:57 +0900, Bill Baxter wrote:
> 
>> Denton Cockburn wrote:
> 
>>> so what I want is this:
>>>
>>> struct Foo
>>>  {
>>>  	int bar;
>>>  	void doStuff(const Foo b)
>>>  	{
>>>  		bar += b.bar; /* I want an error here */
>>>  	}
>> You're not changing b, so you're not going to get an error there.
> 
> You're right, that was a mistake.
> 
> I misphrased my whole query (I misread the compiler error message).
> The concern is still there though, here's a sample of code that produces
> the message.
> 
> struct Foo
> {
> 	int x;
> 	
> 	Foo opMul(const Foo b)
> 	{
> 		Foo f;
> 		f.x = x * b.x;
> 		
> 		return f;
> 	}
> }
> 
> void main()
> {
> 	Foo f;
> 	Foo y;
> 	f.x = 6;
> 	y.x = 7;
> 	
> 	const(Foo) t = f;
> 	Foo p = t * y;
> }
> 
> produces this error:
> test.d(24): function test.Foo.opMul (const(Foo)) does not match parameter types (Foo)
> test.d(24): Error: t.opMul can only be called on a mutable object, not const(Foo)
> 
> 
> So my question SHOULD have been:
> 
> Why can't opMul et al be called on a constant object (reference)?
> 
> Sorry for the previous confusion.

Ok *that's* because saying the parameter is const doesn't mean the 
'this' pointer is const.

To make the hidden 'this' parameter const too you need to use

 const Foo opMul(const Foo b) {...}

That const out front may look like it's modifying the return value, but 
its not.  That would be

 const(Foo) opMul(const Foo b) {...}


--bb
« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home