digitalmars.D.learn - const and non-const member function
- Frank Fischer <frank.fischer s2001.tu-chemnitz.de> Jul 25 2007
- Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> Jul 25 2007
- Chris Nicholson-Sauls <ibisbasenji gmail.com> Jul 25 2007
- James Dennett <jdennett acm.org> Jul 25 2007
- Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> Jul 26 2007
- Frits van Bommel <fvbommel REMwOVExCAPSs.nl> Jul 26 2007
- Christian Kamm <kamm.incasoftware shift-at-left-and-remove-this.de> Jul 26 2007
- Kirk McDonald <kirklin.mcdonald gmail.com> Jul 26 2007
- Regan Heath <regan netmail.co.nz> Jul 26 2007
Hi,
I'm just playing around with const in DMD 2.003 and I have a question.
In C++ it is possible to have a const and a non-const member function with
the same name and parameter types. It depends on the type of the reference
to the object which function is called:
class A {
public:
int myfunc() { return 0; }
int myfunc() const { return 1; }
};
A a;
a.myfunc(); // returns 0
const A& b = a;
b.myfunc(); // returns 1
Is something like this possible in D?
Another example would be with different return-types:
class B {
A a;
public:
A& myfunc() { return a; }
const A& myfunc() { return a; }
};
(of course, in D you don't need explicit references but the idea is the
same).
Furthermore, is it possible to overload opApply(...) so it can be called on
non-const objects and const objects, and the non-const variant has
read-write access:
foreach(ref x; obj) x = 1; // possible for non-const 'obj'
foreach(ref x; cast(const(Obj))obj) x = 1; // ERROR for const 'obj'
foreach(x; obj) writefln("%d", x); // Ok for both, const and non-const 'obj'
What would be the D-way of doing this? I need this access to provide the
correct member functions in some of my D-libraries I write, since I want to
have const-versions of my objects.
Thanks,
Frank
Jul 25 2007
In C++ it is possible to have a const and a non-const member function with the same name and parameter types. ... Is something like this possible in D?
I don't think it's possible (yet). Trying class Foo { void bar() {} const void bar() {} } gives me an error. I'm not sure if it is by design or just not working yet.Furthermore, is it possible to overload opApply(...) so it can be called on non-const objects and const objects, and the non-const variant has read-write access:
Having that would pretty much depend on being able to have a opApply and a const opApply. I tried by using two functions with different names, but the compiler segfaulted on a ref const(Struct*). Cheers, Christian
Jul 25 2007
Christian Kamm wrote:In C++ it is possible to have a const and a non-const member function with the same name and parameter types. ... Is something like this possible in D?
I don't think it's possible (yet). Trying class Foo { void bar() {} const void bar() {} } gives me an error. I'm not sure if it is by design or just not working yet.Furthermore, is it possible to overload opApply(...) so it can be called on non-const objects and const objects, and the non-const variant has read-write access:
Having that would pretty much depend on being able to have a opApply and a const opApply. I tried by using two functions with different names, but the compiler segfaulted on a ref const(Struct*). Cheers, Christian
I may be wrong, but I think the idea is that a method either is or isn't const-safe, and the difference between const and mutable references to the object is supposed to be in the availability of methods, not in their behavior. While I'm sure there's some percentage of the time subtle behavioral changes could be desirable, I don't believe const-method overloading is meant to happen. That said, a few demonstrative cases sometimes do wonders. :) (I'm also not 100% pleased with the 'const R M(){}' syntax for declaring const methods... To me it reads as a function M() returning 'const R'. Yes I know the syntax for that is 'const(R) M(){}' and no I don't have a better idea right off hand. I don't care for the C++ 'R M() const {}' either. Wasn't there something like 'R M:const(){}' volleyed back when the const discussions first happened?) -- Chris Nicholson-Sauls
Jul 25 2007
Chris Nicholson-Sauls wrote:Christian Kamm wrote:In C++ it is possible to have a const and a non-const member function with the same name and parameter types. ... Is something like this possible in D?
I don't think it's possible (yet). Trying class Foo { void bar() {} const void bar() {} } gives me an error. I'm not sure if it is by design or just not working yet.Furthermore, is it possible to overload opApply(...) so it can be called on non-const objects and const objects, and the non-const variant has read-write access:
Having that would pretty much depend on being able to have a opApply and a const opApply. I tried by using two functions with different names, but the compiler segfaulted on a ref const(Struct*). Cheers, Christian
I may be wrong, but I think the idea is that a method either is or isn't const-safe, and the difference between const and mutable references to the object is supposed to be in the availability of methods, not in their behavior. While I'm sure there's some percentage of the time subtle behavioral changes could be desirable, I don't believe const-method overloading is meant to happen. That said, a few demonstrative cases sometimes do wonders. :)
The normal reason (coming from C++) for having overloads by constness is when the return value should differ in constness. The C++ community would frown on code with differences between const and non-const member functions other than those that directly relate to constness. A trivial almost example is any object returning a reference to a component of itself; if the object is const, then the reference to its component should not allow modification, but if the object is non-const, then modification of its component may well be reasonable. (There's a separate debate that I don't want to get into about whether it's poor design to expose references to components. If that's a sticking point to you, imagine that the relationship is "uses" rather than "is composed of".) -- James
Jul 25 2007
I may be wrong, but I think the idea is that a method either is or isn't const-safe, and the difference between const and mutable references to the object is supposed to be in the availability of methods, not in their behavior. While I'm sure there's some percentage of the time subtle behavioral changes could be desirable, I don't believe const-method overloading is meant to happen. That said, a few demonstrative cases sometimes do wonders. :)
Well, the original poster basically wanted it to be possible to have class Container(T) { int opApply(int delegate(ref T) dg); const int opApply(int delegate(ref const(T)) dg); } such that foreach would work on const(Container!(T)) and Container!(T) alike, using the correct types. To me, that seems pretty reasonable. James Dennett pointed out another, simpler example Foo getThis() { return this; } const const(Foo) getThis() { return this; } invariant invariant(Foo) getThis() { return this; } Personally, I'd like to see the 'templating on const' solution that was thrown around during one of the const debates C C(Foo) getThis(constness C)() { return this; } and C int opApply(constness C)(int delegate(ref C(T)) dg) as the different versions are usually quite similar, except for slightly different types.(I'm also not 100% pleased with the 'const R M(){}' syntax for declaring const methods...
Yes, it's quite bad: const Foo func(const Foo) { const Foo = ...; } All consts look the same, but the first means the method, the second is an alternative for const(Foo) and the third is the compile-time const storage class. I'd probably disallow const Foo in parameter declarations, yet don't know how to do make the method-const look different. Cheers, Christian
Jul 26 2007
Christian Kamm wrote:(I'm also not 100% pleased with the 'const R M(){}' syntax for declaring const methods...
Yes, it's quite bad: const Foo func(const Foo) { const Foo = ...; } All consts look the same, but the first means the method, the second is an alternative for const(Foo) and the third is the compile-time const storage class. I'd probably disallow const Foo in parameter declarations, yet don't know how to do make the method-const look different.
How about this for method-const: --- Foo const(func)(const Foo) { // ... } --- Though I guess that may look too much like the const(Type) notation...
Jul 26 2007
I'd probably disallow const Foo in parameter declarations, yet don't know how to do make the method-const look different.
How about this for method-const: --- Foo const(func)(const Foo) { // ... } --- Though I guess that may look too much like the const(Type) notation...
I thought the same thing: putting the const/invariant after the return type might be okay --- Foo const func(const(Foo)) --- but the current way of doing it has the merit of allowing --- const { void func1(); void func2(); } --- which'd be odd to explain with the const being anywhere but in the very front.
Jul 26 2007
Frits van Bommel wrote:Christian Kamm wrote:(I'm also not 100% pleased with the 'const R M(){}' syntax for declaring const methods...
Yes, it's quite bad: const Foo func(const Foo) { const Foo = ...; } All consts look the same, but the first means the method, the second is an alternative for const(Foo) and the third is the compile-time const storage class. I'd probably disallow const Foo in parameter declarations, yet don't know how to do make the method-const look different.
How about this for method-const: --- Foo const(func)(const Foo) { // ... } --- Though I guess that may look too much like the const(Type) notation...
I have a radical notion. We could place it after the parameter list! Foo func(const Foo) const { // ... } -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org
Jul 26 2007
Christian Kamm wrote:Well, the original poster basically wanted it to be possible to have class Container(T) { int opApply(int delegate(ref T) dg); const int opApply(int delegate(ref const(T)) dg); } such that foreach would work on const(Container!(T)) and Container!(T) alike, using the correct types. To me, that seems pretty reasonable.
Initially I thought it would overload on the 'ref' part of the delegate in opApply, eg. class Container { int[] array; //called when 'ref' not used, suitable for 'const' objects int opApply(int delegate(int) dg) { int result = 0; for (int i = 0; i < array.length; i++) { result = dg(array[i]); if (result) break; } return result; } //called when 'ref' used, not suitable for 'const' objects int opApply(int delegate(ref int) dg) { int result = 0; for (int i = 0; i < array.length; i++) { result = dg(array[i]); if (result) break; } return result; } } Current D implementation expects the delegate to have 'ref' in it, anything else is an error and foreach on a const object gives: Error: a.opApply can only be called on a mutable object Instead it could, on a const object look for: int opApply(int delegate(Type) dg) and on non-const: int opApply(int delegate(ref Type) dg) Regan
Jul 26 2007









James Dennett <jdennett acm.org> 