November 29, 2018
On Thursday, 29 November 2018 at 18:49:27 UTC, Steven Schveighoffer wrote:

> Ah, ok. Essentially you are looking for the layout of the local variables.
>
> One thing that is available for D is the compile-time property offsetof, which gives the offset from the start of an aggregate that an item is.
>
> for example:
>
> struct S
> {
>   int x;
>   bool y;
> }
>
> static assert(S.y.offsetof == 4);
>
> So while this isn't available for function locals, the idea is similar. But I don't think there's an equivalent to what you are able to do here in C++.
>
> I don't think it would be a huge stretch to apply this same property to function locals, but it would require an enhancement request.


This is an interesting idea.

Somehow it would be helpful to access the frame pointer, too, from the variable. Obtaining this offset via the variable would enable disambiguation between variables with the same local offset but from different functions.


The example would then read something like:

auto cmp(T, U)(const ref T t, const ref U u)
{
  // i.e.
  //   t.frame.offsetof := &main;
  //   t.offsetof := main.c0.offsetof;

  enum f = t.frame.offsetof == u.frame.offsetof;
  enum v = t.offsetof == u.offsetof;
  return f && v;
}

void main()
{
  auto c0 = 1;
  auto c1 = 2;

  static assert(cmp(c0, c0));
  static assert(!cmp(c0, c1));
}

November 29, 2018
On 11/29/18 5:56 PM, Dominic Jones wrote:
> On Thursday, 29 November 2018 at 18:49:27 UTC, Steven Schveighoffer wrote:
> 
>> Ah, ok. Essentially you are looking for the layout of the local variables.
>>
>> One thing that is available for D is the compile-time property offsetof, which gives the offset from the start of an aggregate that an item is.
>>
>> for example:
>>
>> struct S
>> {
>>   int x;
>>   bool y;
>> }
>>
>> static assert(S.y.offsetof == 4);
>>
>> So while this isn't available for function locals, the idea is similar. But I don't think there's an equivalent to what you are able to do here in C++.
>>
>> I don't think it would be a huge stretch to apply this same property to function locals, but it would require an enhancement request.
> 
> 
> This is an interesting idea.
> 
> Somehow it would be helpful to access the frame pointer, too, from the variable. Obtaining this offset via the variable would enable disambiguation between variables with the same local offset but from different functions.

Hm... the offsetof feature would break down there. But perhaps a frame (or probably __traits call) could provide the function symbol, so you could do:

static assert(t.frame is u.frame);

Strawman could be __traits(getAggregate, sym) => symbol that contains sym, be it a function or struct or whatever.

> 
> 
> The example would then read something like:
> 
> auto cmp(T, U)(const ref T t, const ref U u)
> {
>    // i.e.
>    //   t.frame.offsetof := &main;
>    //   t.offsetof := main.c0.offsetof;
> 
>    enum f = t.frame.offsetof == u.frame.offsetof;
>    enum v = t.offsetof == u.offsetof;
>    return f && v;
> }
> 
> void main()
> {
>    auto c0 = 1;
>    auto c1 = 2;
> 
>    static assert(cmp(c0, c0));
>    static assert(!cmp(c0, c1));
> }
> 

I was thinking you'd do it with D compile time features:

bool cmp(alias var1, alias var2) = var1.offsetof == var2.offsetof;

struct S
{
   int x;
   int y;
}

// this actually works today:
static assert(cmp!(S.x, S.x));
static assert(!cmp!(S.x, S.y));

void main()
{
   auto c0 = 1;
   auto c1 = 2;

   // proposed
   static assert(cmp!(c0, c0));
   static assert(!cmp!(c0, c1));
}

-Steve
November 30, 2018
On Thursday, 29 November 2018 at 15:56:54 UTC, Dominic Jones wrote:
> Hello,
>
> I would like to capture the "address" of variables at compile time. Something not far from this can be done in C++, namely addresses can be compared but not captured (then compared, or whatever).
>
> [...]

I think you can do that by using aliases. This seems to work:

auto cmp(alias t, alias u)() {
  return &t == &u;
}

void main() {
  auto c0 = 1;
  auto c1 = 2;
  static assert(cmp!(c0, c0));
  static assert(!cmp!(c0, c1));
}

Cheers,
- Ali
November 29, 2018
On 11/29/18 7:23 PM, aliak wrote:
> On Thursday, 29 November 2018 at 15:56:54 UTC, Dominic Jones wrote:
>> Hello,
>>
>> I would like to capture the "address" of variables at compile time. Something not far from this can be done in C++, namely addresses can be compared but not captured (then compared, or whatever).
>>
>> [...]
> 
> I think you can do that by using aliases. This seems to work:
> 
> auto cmp(alias t, alias u)() {
>    return &t == &u;
> }
> 
> void main() {
>    auto c0 = 1;
>    auto c1 = 2;
>    static assert(cmp!(c0, c0));
>    static assert(!cmp!(c0, c1));
> }

Sweet :) wish I had thought of that earlier...

-Steve
November 30, 2018
On Friday, 30 November 2018 at 00:23:08 UTC, aliak wrote:


> I think you can do that by using aliases. This seems to work:
>
> auto cmp(alias t, alias u)() {
>   return &t == &u;
> }
>
> void main() {
>   auto c0 = 1;
>   auto c1 = 2;
>   static assert(cmp!(c0, c0));
>   static assert(!cmp!(c0, c1));
> }

Unfortunately, with the solution above, the variables are passed as template arguments. Somehow, I need to have the variables being passed as regular arguments since my intended use case is operator overloading for expression trees.


Consider the example, below: somehow, I need to be able to know the nominal addresses of parameters passed into 'opBinary' so that the 'Binary' template may be defined with address tags which relate to the operands of 'opBinary'. If the types and tags of the two variables match then there may be a guarantee (at the file scope) that the arguments are indeed the same.

struct Terminal
{
  auto opBinary(string op, R)(const ref R r)
  {
     enum l_adr = 0; // proposed: this.scope.offsetof + this.offsetof;
     enum r_adr = 4; // proposed: r.scope.offsetof + r.offsetof;

     return Binary!(op, typeof(this), R, l_adr, r_adr)(this, r);
  }
}

struct Binary(string op, L, R, int l_adr, int r_adr)
{
  L l;
  R r;
}

void main()
{
  Terminal c0;
  Terminal c1;
  pragma(msg, typeof(c0 + c1)); // 'Binary!("+", Terminal, Terminal, 0, 4)'

  // pragma(msg, typeof(transform(c0 + c0))); // becomes:  "2 * c0"
  // pragma(msg, typeof(transform(c0 + c1))); // becomes: "c0 + c1"
}

(at: https://run.dlang.io/is/hwVI5n)


-Dominic
1 2
Next ›   Last »