Jump to page: 1 2
Thread overview
const member function
Feb 21, 2015
rumbu
Feb 21, 2015
Baz
Feb 21, 2015
rumbu
Feb 21, 2015
Mike Parker
Feb 21, 2015
rumbu
Feb 21, 2015
Jonathan M Davis
Feb 21, 2015
ketmar
Feb 21, 2015
Foo
Feb 23, 2015
rumbu
Feb 23, 2015
ketmar
Feb 24, 2015
Jonathan M Davis
Feb 21, 2015
Baz
Feb 21, 2015
Foo
February 21, 2015
Often I'm using the following code pattern:

class S
{
   private SomeType cache;

   public SomeType SomeProp() @property
   {
      if (cache is null)
        cache = SomeExpensiveOperation();
      return cache;
   }
}

Is there any way to mark SomeProp() as const? Because I want to call somewhere const(S).SomeProp, which for the outside world is must be "const", returning just a value, even that internaly it modifies the internal S structure.
February 21, 2015
---
class S
{
    private SomeType cache;

    public const(SomeType) SomeProp() @property
    {
       if (cache is null)
         cache = SomeExpensiveOperation();
       return cache;
    }
}
---

the result of the getter will be read-only
February 21, 2015
On Saturday, 21 February 2015 at 07:01:12 UTC, Baz wrote:
> ---
> class S
> {
>     private SomeType cache;
>
>     public const(SomeType) SomeProp() @property
>     {
>        if (cache is null)
>          cache = SomeExpensiveOperation();
>        return cache;
>     }
> }
> ---
>
> the result of the getter will be read-only

My intention is not to have a read-only getter, I want to call SomeProp on a const object:

class S
{
    private int cache = -1;
    private int SomeExpensiveOp() { return 12345; }

    public @property const(int) SomeProp()
    {
        if (cache = -1)
            cache = SomeExpensiveOp();
        return cache;
    }
}

unittest
{
    const(S) s = new S();
    auto i = s.SomeProp;  //mutable method S.SomeProp is not callable using a const object
}
February 21, 2015
On 2/21/2015 4:31 PM, rumbu wrote:

> My intention is not to have a read-only getter, I want to call SomeProp
> on a const object:
>
> class S
> {
>      private int cache = -1;
>      private int SomeExpensiveOp() { return 12345; }
>
>      public @property const(int) SomeProp()
>      {
>          if (cache = -1)
>              cache = SomeExpensiveOp();
>          return cache;
>      }
> }
>

const is transitive. If an instance of S is const, then all of its members are const, too. You cannot modify cache in that case. Assuming cache only needs to be initialized once, you can do this instead:

    this() { cache = SomeExpensiveOp(); }

    public @property const(int) SomeProp() const
    {
        return cache;
    }

Notice the const on the end of SomeProp. That makes the function callable on a const instance, but you still cannot modify cache inside of it.



February 21, 2015
On Saturday, 21 February 2015 at 08:08:25 UTC, Mike Parker wrote:
> On 2/21/2015 4:31 PM, rumbu wrote:
>
> you can do this instead:
>
>     this() { cache = SomeExpensiveOp(); }
>
>     public @property const(int) SomeProp() const
>     {
>         return cache;
>     }
>
> Notice the const on the end of SomeProp. That makes the function callable on a const instance, but you still cannot modify cache inside of it.

My question was not how I do this, I know already. My question was if there is another way to safely call a non-const instance function on a const object.

Initializing "cache" in the constructor will defeat the cache mechanism itself an that's I want to avoid.
February 21, 2015
On Saturday, 21 February 2015 at 07:31:19 UTC, rumbu wrote:
> On Saturday, 21 February 2015 at 07:01:12 UTC, Baz wrote:
>> ---
>> class S
>> {
>>    private SomeType cache;
>>
>>    public const(SomeType) SomeProp() @property
>>    {
>>       if (cache is null)
>>         cache = SomeExpensiveOperation();
>>       return cache;
>>    }
>> }
>> ---
>>
>> the result of the getter will be read-only
>
> My intention is not to have a read-only getter, I want to call SomeProp on a const object:
>
> class S
> {
>     private int cache = -1;
>     private int SomeExpensiveOp() { return 12345; }
>
>     public @property const(int) SomeProp()
>     {
>         if (cache = -1)
>             cache = SomeExpensiveOp();
>         return cache;
>     }
> }
>
> unittest
> {
>     const(S) s = new S();
>     auto i = s.SomeProp;  //mutable method S.SomeProp is not callable using a const object
> }

right, i have not carefully read the body of the Q. my bad.

February 21, 2015
On Saturday, February 21, 2015 08:27:13 rumbu via Digitalmars-d-learn wrote:
> On Saturday, 21 February 2015 at 08:08:25 UTC, Mike Parker wrote:
> > On 2/21/2015 4:31 PM, rumbu wrote:
> >
> > you can do this instead:
> >
> >     this() { cache = SomeExpensiveOp(); }
> >
> >     public @property const(int) SomeProp() const
> >     {
> >         return cache;
> >     }
> >
> > Notice the const on the end of SomeProp. That makes the function callable on a const instance, but you still cannot modify cache inside of it.
>
> My question was not how I do this, I know already. My question was if there is another way to safely call a non-const instance function on a const object.
>
> Initializing "cache" in the constructor will defeat the cache mechanism itself an that's I want to avoid.

Nope. If you want to use caching, you can't do it with const. D's const is transitive, and it's not logical const. It's physical const. If _any_ portion of an object were to be mutated by a const function, it would violate the type system. Unlike C++'s const, D's const provides actual guarantees about the data not changing, which can be useful for some optimizations but is outright required because of immutable. For instance, imagine if your object were immutable and your const function were somehow able to mutate on of the object's members (e.g. by casting away const). An immutable object could be in read-only-memory, in which case, that would segfault. And even if it didn't, it could cause really weird bugs due to the fact that the compiler is free to assume that an immutable object never changes and that an object can never be mutated via a const reference. The fact that immutable objects are implicitly shared would make it even worse, because then you'd risk thread-related issues to boot.

The reality of the matter is that if you want to do any kind of caching like this, you either have to do the caching only in mutable functions (in which case, the const function could take advantage of the cached value if it were there but would have to calculate it if it hadn't been cached already), or you can't do caching at all.

Ultimately, for better or worse, D's const is a very different beast from C++'s const, and you can't approach them the same way.

This SO question discusses the issue:

http://stackoverflow.com/questions/4219600/logical-const-in-d

- Jonathan M Davis

February 21, 2015
On Saturday, 21 February 2015 at 06:38:18 UTC, rumbu wrote:
> Often I'm using the following code pattern:
>
> class S
> {
>    private SomeType cache;
>
>    public SomeType SomeProp() @property
>    {
>       if (cache is null)
>         cache = SomeExpensiveOperation();
>       return cache;
>    }
> }
>
> Is there any way to mark SomeProp() as const? Because I want to call somewhere const(S).SomeProp, which for the outside world is must be "const", returning just a value, even that internaly it modifies the internal S structure.

AFAIK it is unsafe and not recommended, but this works for me:

----
import std.stdio;

class Foo {
    void say(string s) const {
        writeln(s);
    }
}

class Bar {
    Foo f;

    const(Foo) getFoo() const {
        if (!f)
            cast() this.f = new Foo();
        return f;
    }
}

void main() {
    Bar b = new Bar();
    const Foo f = b.getFoo();
    f.say("Hello");
}
----
February 21, 2015
On Sat, 21 Feb 2015 08:27:13 +0000, rumbu wrote:

> My question was not how I do this, I know already. My question was if there is another way to safely call a non-const instance function on a const object.

is there a way to been safely hit by a truck?

February 21, 2015
On Saturday, 21 February 2015 at 15:26:28 UTC, ketmar wrote:
> On Sat, 21 Feb 2015 08:27:13 +0000, rumbu wrote:
>
>> My question was not how I do this, I know already. My question was if
>> there is another way to safely call a non-const instance function on a
>> const object.
>
> is there a way to been safely hit by a truck?

In a tank. ;)
« First   ‹ Prev
1 2