Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
July 25, 2007 const and non-const member function | ||||
---|---|---|---|---|
| ||||
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 |
July 25, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frank Fischer | > 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 |
July 25, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Kamm | 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
|
July 26, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | 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
|
July 26, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Chris Nicholson-Sauls | > 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 |
July 26, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Kamm | 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...
|
July 26, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frits van Bommel | >> 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.
|
July 26, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frits van Bommel | 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 |
July 26, 2007 Re: const and non-const member function | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Kamm | 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
|
Copyright © 1999-2021 by the D Language Foundation