View mode: basic / threaded / horizontal-split · Log in · Help
November 04, 2012
question on [Issue 7853]
This bug has no comments. The original says: "The fix is obvious:
redefine postblit as this(const this); but it isn't always obvious
when looking at hundreds of lines of code...."

Is this accepted/correct? In the following if I include the 
this(const
this) postblit it does not get called. It makes me question if 
the fix
is obvious?

Thanks
Dan


-------
import std.stdio;

struct S {
  static if(false) {
    this (const this) { writeln("const postblit");}
  } else {
    this (this) { writeln("non-const postblit");}
  }
}
void main () {
  const(S) s;
  S s2 = s;
}
November 04, 2012
Re: question on [Issue 7853]
On 04.11.2012 21:49, Dan wrote:
>
> This bug has no comments. The original says: "The fix is obvious:
> redefine postblit as this(const this); but it isn't always obvious
> when looking at hundreds of lines of code...."
>
> Is this accepted/correct? In the following if I include the this(const
> this) postblit it does not get called. It makes me question if the fix
> is obvious?
>

I don't think that currently qualifiers work with the postblit 
constructor. See here for a related discussion.

http://forum.dlang.org/thread/CAFDvkcvvL8GxHQB=Rw9pTm-uxOKzNGVQNDv9w5Os3SkQCc=DLQ@mail.gmail.com
November 05, 2012
Re: question on [Issue 7853]
On Sunday, 4 November 2012 at 21:44:15 UTC, Tobias Pankrath wrote:

> I don't think that currently qualifiers work with the postblit 
> constructor. See here for a related discussion.
>
> http://forum.dlang.org/thread/CAFDvkcvvL8GxHQB=Rw9pTm-uxOKzNGVQNDv9w5Os3SkQCc=DLQ@mail.gmail.com

Thanks. The reason I'm down this path is something like below. I 
really want to keep const ref for parms on a method (e.g. foo 
below). It turns out the type is a assoc array and length and 
keys are both giving me a headache. Without the cast I get a 
message like:

Error: function acct.Account.__postblit () is not callable using 
argument types () const

Below I cast away const (Dohh!). Is it safe in this case?
If not is there another way?

Thanks,
Dan

import std.stdio;
import std.traits;

alias Account[string] Map;

struct Account {
  this(this){ writeln("acct copied"); }
}

void foo(const ref Map m) {
  pragma(msg, "Map is ", typeof(m));
  pragma(msg, "Map is ", typeof(cast()m));
  writeln("Map has ", (cast(Map)m).length);
  writeln("Map has ", (cast(Map)m).keys);
}

void main() {
  Map map;
  Account acct;
  foo(map);
}
November 05, 2012
Re: question on [Issue 7853]
On 11/05/2012 02:24 AM, Dan wrote:

> Thanks. The reason I'm down this path is something like below. I really
> want to keep const ref for parms on a method (e.g. foo below). It turns
> out the type is a assoc array and length and keys are both giving me a
> headache. Without the cast I get a message like:
>
> Error: function acct.Account.__postblit () is not callable using
> argument types () const

You probably now this, but this error message indicates that you want to 
call a non-const method of a const instance.

> Below I cast away const (Dohh!). Is it safe in this case?
Casting away const is okay as long as you don't change a single bit of 
your data.

> If not is there another way?

The code below works, too. But to be honest, I don't now why the 
compiler complains that the postblit is not callable in your version but 
does not actually get called in mine.

-----
alias Account[string] Map;

struct Account {
      this(this) const { writeln("acct copied"); }
      //this(this) { writeln("acct copied"); }
}

void foo(const ref Map m) {
    pragma(msg, "Map is ", typeof(m));
    pragma(msg, "Map is ", typeof(cast()m));
    writeln("Map has ", m.length);
    writeln("Map has ", m.keys);
}

void main()
{
    Map map;

    Account acct;
    foo(map);
    Account acct2 = acct;
}
-----
I have added the copy construction of acct2 to verify that the 
const-qualified this(this) is actually used for postblit.
November 05, 2012
Re: question on [Issue 7853]
On Monday, 5 November 2012 at 09:10:41 UTC, Tobias Pankrath wrote:

> Casting away const is okay as long as you don't change a single 
> bit of your data.
>

Yes, thanks. Makes sense. I need to know not only what I might be 
mutating, but also code I call. In this specific case, though I 
hope all of these things on assoc arrays are safe, const or not, 
so my cast is harmless.
- length
- keys - returning dynamic array I won't change
- values - returning dynamic array I won't change
- foreach

I have not figured what to look at for associative arrays. For 
example, in .../druntime/import/object.di there is a struct 
called AssociativeArray which I imagine the [ "foo" : "goo" ] 
syntactic sugar gets me to. It has the keys property as non-const 
and internally it does a cast:
    Key[] keys() @property
    {
        auto a = _aaKeys(p, Key.sizeof);
        return *cast(Key[]*) &a;
    }
I'm not even sure if this is the right code to look at when 
dealing with associative arrays described in TDPL?

>> If not is there another way?
>
> The code below works, too. But to be honest, I don't now why 
> the compiler complains that the postblit is not callable in 
> your version but does not actually get called in mine.
>

My theory: you must use this(this) without variation for postblit 
to even get called until they hammer out the issues on the thread 
you referred to. While the signature below gets called, it is 
futile since incipient instance can not be patched which is the 
purpose. I think <this(this) const> should not be allowed but 
this(const ref this) or this(const this) should be allowed and 
preferred. I don't understand how the compiler ends up with the 
postblit message without the cast. I hope the lack of const on 
assoc array properties and foreach are oversights rendering the 
casts safe and on a future release of D rendering them 
unnecessary.

Thanks
Dan

> -----
> alias Account[string] Map;
>
> struct Account {
>       this(this) const { writeln("acct copied"); }
>       //this(this) { writeln("acct copied"); }
> }
November 05, 2012
Re: question on [Issue 7853]
On 11/05/2012 12:43 PM, Dan wrote:
> On Monday, 5 November 2012 at 09:10:41 UTC, Tobias Pankrath wrote:


> I have not figured what to look at for associative arrays. For example,
> in .../druntime/import/object.di there is a struct called
> AssociativeArray which I imagine the [ "foo" : "goo" ] syntactic sugar
> gets me to. It has the keys property as non-const and internally it does
> a cast:
>      Key[] keys() @property
>      {
>          auto a = _aaKeys(p, Key.sizeof);
>          return *cast(Key[]*) &a;
>      }
> I'm not even sure if this is the right code to look at when dealing with
> associative arrays described in TDPL?

AA are implemented in object_.d, rt/aaA.d and in the compiler. For 
example the _aaKeys function is defined in rt/aaA.d.

I don't now any details though. You may take a look here: 
http://www.digitalmars.com/d/archives/digitalmars/D/Replacing_AA_s_in_druntime_161307.html


>>
>> The code below works, too. But to be honest, I don't now why the
>> compiler complains that the postblit is not callable in your version
>> but does not actually get called in mine.
>>
>
>  While the signature below gets called, it is futile since
> incipient instance can not be patched which is the purpose.
Yeah your are right here.
> I think
> <this(this) const> should not be allowed but this(const ref this) or
> this(const this) should be allowed and preferred.
The problem is, that you actually don't have access to the original 
struct. So it's not clear how to define the semantics of this(const this).

> I don't understand how
> the compiler ends up with the postblit message without the cast. I hope
> the lack of const on assoc array properties and foreach are oversights
> rendering the casts safe and on a future release of D rendering them
> unnecessary.

I guess so.
Top | Discussion index | About this forum | D home