Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
December 13, 2013 const method and return type | ||||
---|---|---|---|---|
| ||||
class A { auto getter() const { return property; } int property = 0; } Please notice that getter method is marked as const. Why this method return "const int"? If i force it declaring: int getter() const it returns "int". It takes me a lot to understand where the issue was in my code. Is it a bug? |
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | On Friday, 13 December 2013 at 23:46:14 UTC, Andrea Fontana wrote:
> class A
> {
> auto getter() const
> {
> return property;
> }
>
> int property = 0;
>
> Why this method return "const int"?
Inside getter, "this" is const. Due to transitive const, all the members through this are const too.
So inside getter, property is a const int. The auto return value returns the *exact* type, thus const.
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | I read:
Const Member Functions
Const member functions are functions that are not allowed to change any part of the object through the member function's this reference.
I'm not changing anything. Just returning it.
Is this a try to avoid something like the following, then?
... B getter() const { return this.b; }
... void getter2() const { B var = getter(); var.non_const_method(); }
I don't think it's the right way, is it?
getter2() shouldn't be allowed becouse var is a reference to this.b, that's ok. But enforcing constness of return type IMHO is wrong.
Something like:
void main()
{
B value = myclass.getter();
b.non_const();
}
seems correct to me. Also this seems correct:
void getter2() /*non-const*/ { getter().non_const_method(); }
On Saturday, 14 December 2013 at 00:01:31 UTC, Adam D. Ruppe wrote:
> On Friday, 13 December 2013 at 23:46:14 UTC, Andrea Fontana wrote:
>> class A
>> {
>> auto getter() const
>> {
>> return property;
>> }
>>
>> int property = 0;
>>
>> Why this method return "const int"?
>
> Inside getter, "this" is const. Due to transitive const, all the members through this are const too.
>
> So inside getter, property is a const int. The auto return value returns the *exact* type, thus const.
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | Just another thought. If we have:
class B;
struct C;
class A
{
void method() const { ... }
B another_class;
C a_struct;
}
B is just a reference to a object, so method() should not reassign it. The reference should be const, not the object itself. method() should be able to call mutable another_class methods. Am I wrong?
Instead "a_struct" is not a reference, so method() should not edit it, this makes sense. You can return a copy or a const ref of a struct-member
On Saturday, 14 December 2013 at 00:09:03 UTC, Andrea Fontana wrote:
> I read:
>
> Const Member Functions
> Const member functions are functions that are not allowed to change any part of the object through the member function's this reference.
>
> I'm not changing anything. Just returning it.
>
> Is this a try to avoid something like the following, then?
>
> ... B getter() const { return this.b; }
> ... void getter2() const { B var = getter(); var.non_const_method(); }
>
> I don't think it's the right way, is it?
> getter2() shouldn't be allowed becouse var is a reference to this.b, that's ok. But enforcing constness of return type IMHO is wrong.
>
> Something like:
>
> void main()
> {
> B value = myclass.getter();
> b.non_const();
> }
>
> seems correct to me. Also this seems correct:
>
> void getter2() /*non-const*/ { getter().non_const_method(); }
>
>
>
> On Saturday, 14 December 2013 at 00:01:31 UTC, Adam D. Ruppe wrote:
>> On Friday, 13 December 2013 at 23:46:14 UTC, Andrea Fontana wrote:
>>> class A
>>> {
>>> auto getter() const
>>> {
>>> return property;
>>> }
>>>
>>> int property = 0;
>>>
>>> Why this method return "const int"?
>>
>> Inside getter, "this" is const. Due to transitive const, all the members through this are const too.
>>
>> So inside getter, property is a const int. The auto return value returns the *exact* type, thus const.
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | On Saturday, 14 December 2013 at 00:09:03 UTC, Andrea Fontana wrote:
> I'm not changing anything. Just returning it.
Right, it is just that "auto" keeps the exact type, and in the const method, the exact type of the members are all const too since that's how the language enforces that you don't change anything.
You are allowed implicitly cast const(int) to int, which is why the version that specifically returns int works, it is just that auto doesn't do any implicit conversions.
The same thing happens if you do
const(int) a = 10;
auto foo = a;
foo = 0; // test500.d(5): Error: cannot modify const expression foo
The auto var decl there keeps const too. There's some discussion that auto might strip off the top level const where it is otherwise allowed, but I'm not sure if that's actually going to happen or not.
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | On Saturday, 14 December 2013 at 00:24:01 UTC, Andrea Fontana wrote:
> Just another thought. If we have:
>
> class B;
> struct C;
>
> class A
> {
> void method() const { ... }
> B another_class;
> C a_struct;
> }
>
> B is just a reference to a object, so method() should not reassign it. The reference should be const, not the object itself. method() should be able to call mutable another_class methods. Am I wrong?
Yes, in D, all members of a const object are const too. So inside method() const, another_class is const. Which means another_class.member is also const.
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | On Friday, 13 December 2013 at 23:46:14 UTC, Andrea Fontana wrote:
> class A
> {
> auto getter() const
> {
> return property;
> }
>
> int property = 0;
> }
>
>
> Please notice that getter method is marked as const. Why this method return "const int"?
`const` as a function attribute just marks the implicit this-reference parameter as const - apart from the necessary syntax deviation, it works like any other parameter. Thus, inside `getter`, `typeof(this)` is `const(A)`, and since const is transitive, that means `typeof(this.property)` is `const(int)`.
If you explicitly specify the return type as `int`, then `property` is implicitly converted from `const(int)` to `int`, which is legal since `int` has no mutable indirection.
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adam D. Ruppe | On Saturday, 14 December 2013 at 00:31:24 UTC, Adam D. Ruppe wrote:
> On Saturday, 14 December 2013 at 00:24:01 UTC, Andrea Fontana wrote:
>> Just another thought. If we have:
>>
>> class B;
>> struct C;
>>
>> class A
>> {
>> void method() const { ... }
>> B another_class;
>> C a_struct;
>> }
>>
>> B is just a reference to a object, so method() should not reassign it. The reference should be const, not the object itself. method() should be able to call mutable another_class methods. Am I wrong?
>
> Yes, in D, all members of a const object are const too. So inside method() const, another_class is const. Which means another_class.member is also const.
Why? The object itself it's not a member. The reference to that object is the member.
Consider this:
class A {}
class B
{
A first;
A second;
}
void main()
{
auto a = new A;
auto b = new B;
b.first = a;
b.second = a;
assert(b.first == b.second);
assert(&b.first == &b.second);
}
Second assert fail, of course.
"first" and "second" are just two reference. They are different reference to the same object.
Those reference should be const, not the object they refer.
Consider this way to escape current constness:
class A { int x; }
A globalA;
class B
{
void method() const
{
// first.x = 10; This doesn't work. But IMO it should
globalA.x = 10; // This work. Same effect as preceding line
writeln(first.x); // 10!
}
A first;
A second;
}
void main()
{
globalA = new A;
auto b = new B;
b.first = globalA;
b.second = globalA;
b.method();
}
You see?
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | On Saturday, 14 December 2013 at 00:53:27 UTC, Andrea Fontana wrote:
> Consider this way to escape current constness:
This isn't "escaping" constness. Const only means mutation is prevented through that particular reference. It is distinct from immutability.
|
December 14, 2013 Re: const method and return type | ||||
---|---|---|---|---|
| ||||
Posted in reply to Andrea Fontana | On 12/13/2013 04:24 PM, Andrea Fontana wrote: > Just another thought. If we have: > > class B; > struct C; > > class A > { > void method() const { ... } > B another_class; > C a_struct; > } > > B is just a reference to a object, so method() should not reassign it. > The reference should be const, not the object itself. method() should be > able to call mutable another_class methods. However, according to how D sees constness, mutating another_class through its non-const methods would mutate the state of A as well. Ali |
Copyright © 1999-2021 by the D Language Foundation