www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - const method and return type

reply "Andrea Fontana" <nospam example.com> writes:
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?
Dec 13 2013
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Dec 13 2013
parent reply "Andrea Fontana" <nospam example.com> writes:
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.
Dec 13 2013
next sibling parent reply "Andrea Fontana" <nospam example.com> writes:
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.
Dec 13 2013
next sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Dec 13 2013
parent reply "Andrea Fontana" <nospam example.com> writes:
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?
Dec 13 2013
parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
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.
Dec 13 2013
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Dec 14 2013
prev sibling parent reply "Adam D. Ruppe" <destructionator gmail.com> writes:
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.
Dec 13 2013
parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
On 12/13/2013 04:30 PM, Adam D. Ruppe wrote:

 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.
Ah. I was about to respond by "that top level const is silly" but I now see that it is true only when no mutable reference is involved. So, in order to keep things simple, now I think that the current behavior is better. Ali
Dec 14 2013
prev sibling parent "Jakob Ovrum" <jakobovrum gmail.com> writes:
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.
Dec 13 2013