Jump to page: 1 2 3
Thread overview
opMul
Mar 02, 2008
Denton Cockburn
Mar 03, 2008
Simen Kjaeraas
Mar 03, 2008
Bill Baxter
Mar 03, 2008
Simen Kjaeraas
Mar 03, 2008
Walter Bright
Mar 03, 2008
Bill Baxter
Mar 04, 2008
Simen Kjaeraas
Mar 04, 2008
Bill Baxter
Mar 04, 2008
Denton Cockburn
Mar 04, 2008
Janice Caron
Mar 03, 2008
Denton Cockburn
Mar 03, 2008
Simen Kjaeraas
Mar 03, 2008
Denton Cockburn
Mar 03, 2008
Bill Baxter
Mar 03, 2008
Denton Cockburn
Mar 03, 2008
Bill Baxter
Mar 03, 2008
Denton Cockburn
Mar 04, 2008
Denton Cockburn
Mar 06, 2008
Bill Baxter
Mar 06, 2008
Koroskin Denis
Mar 06, 2008
Janice Caron
Mar 08, 2008
Dave
Mar 08, 2008
Janice Caron
Mar 08, 2008
Simen Kjaeraas
Mar 09, 2008
Dave
Mar 08, 2008
Dave
Mar 09, 2008
Dave
Mar 08, 2008
Janice Caron
Mar 06, 2008
Simen Kjaeraas
Mar 06, 2008
Janice Caron
March 02, 2008
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
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
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
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
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
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
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
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
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
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