Thread overview | ||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Bill Baxter | 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 | ||||
---|---|---|---|---|
| ||||
Posted in reply to Denton Cockburn | 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
|
Copyright © 1999-2021 by the D Language Foundation