Jump to page: 1 2
Thread overview
Anyway to achieve the following
Aug 13, 2021
JG
Aug 13, 2021
Tejas
Aug 13, 2021
Rekel
Aug 13, 2021
H. S. Teoh
Aug 13, 2021
JG
Aug 13, 2021
pilger
Aug 13, 2021
Ali Çehreli
Aug 13, 2021
Paul Backus
Aug 14, 2021
Carl Sturtivant
Aug 15, 2021
JG
Aug 15, 2021
Paul Backus
Aug 15, 2021
Johan
Aug 15, 2021
Carl Sturtivant
Aug 16, 2021
JG
Aug 17, 2021
Johan
Aug 17, 2021
Rekel
August 13, 2021

Suppose one has a pointer p of type T*.
Can on declare variable a of type T which is stored in the location pointed to by p?

As an example if we have:

struct S
{
  int x = 1234;
}

void main() {
   S s;
   //unknown construction of a using &(s.x)
   writeln(a); //displays 1234
   s.x = s.x+1;
   writeln(a); //displays 1235
   a = a +1;
   writeln(s.x); //displays 1236
}

Similar behavior can be achieved in the body of the lambda here

import std.stdio;

struct S
{
  int x = 1234;
}


void main() {
    S s;
    (ref a){
         writeln(a);
         s.x = s.x + 1;
         writeln(a);
         a = a +1;
         writeln(s.x);
    }(s.x);
}
August 13, 2021

On Friday, 13 August 2021 at 08:25:33 UTC, JG wrote:

>

Suppose one has a pointer p of type T*.
Can on declare variable a of type T which is stored in the location pointed to by p?

As an example if we have:

struct S
{
  int x = 1234;
}

void main() {
   S s;
   //unknown construction of a using &(s.x)
   writeln(a); //displays 1234
   s.x = s.x+1;
   writeln(a); //displays 1235
   a = a +1;
   writeln(s.x); //displays 1236
}

Similar behavior can be achieved in the body of the lambda here

import std.stdio;

struct S
{
  int x = 1234;
}


void main() {
    S s;
    (ref a){
         writeln(a);
         s.x = s.x + 1;
         writeln(a);
         a = a +1;
         writeln(s.x);
    }(s.x);
}

Umm is this what you want?

import std.stdio;

struct S
{
  int x = 1234;
}


void main() {
    S s;
    /*(ref a){
         writeln(a);
         s.x = s.x + 1;
         writeln(a);
         a = a +1;
         writeln(s.x);
    }(s.x);*/

    auto a = &(s.x);
    writeln(*a);
    s.x += 1;
    writeln(*a);
    *a += 1;
    writeln(s.x);


}
August 13, 2021
On 8/13/21 1:25 AM, JG wrote:

> Suppose one has a pointer p of type T*.
> Can on declare variable a of type T which is stored in the location
> pointed to by p?

You may be looking for core.lifetime.emplace. (core.lifetime is not on dlang.org at the moment for me but it is under /usr/include/dmd/druntime/import/core on my computer.)

I have some content about 'emplace' but it is not in std.conv anymore:

  http://ddili.org/ders/d.en/memory.html#ix_memory.construction,%20emplace

Ali

August 13, 2021
On Friday, 13 August 2021 at 09:30:25 UTC, Ali Çehreli wrote:
> (core.lifetime is not on dlang.org at the moment for me but it is under /usr/include/dmd/druntime/import/core on my computer.)

It's also on dpldocs.info:

https://dpldocs.info/experimental-docs/core.lifetime.html
August 13, 2021

On Friday, 13 August 2021 at 09:10:18 UTC, Tejas wrote:

>

On Friday, 13 August 2021 at 08:25:33 UTC, JG wrote:

>

Suppose one has a pointer p of type T*.
Can on declare variable a of type T which is stored in the location pointed to by p?
Umm is this what you want?

import std.stdio;

struct S
{
  int x = 1234;
}


void main() {
    S s;
    /*(ref a){
         writeln(a);
         s.x = s.x + 1;
         writeln(a);
         a = a +1;
         writeln(s.x);
    }(s.x);*/

    auto a = &(s.x);
    writeln(*a);
    s.x += 1;
    writeln(*a);
    *a += 1;
    writeln(s.x);


}

That's also what I thought, although at first I thought JG meant dereferencing a pointer to a type without reallocating the content.

In a way comparable to aliasing A* or having your original data be a union in the first place.
It seems however one can use . when using pointers, which is cool, though there seem to be some caveats: https://forum.dlang.org/post/hthxvxxsxdpkvwcwgisi@forum.dlang.org (note this is 2014...))

For anyone more experienced with C, I'm not well known with references but are those semantically similar to the idea of using a type at a predefined location?

Small sidenote, this would be cool:

int* ip = cast(int*)other_pointer;
int a = #a; // like a dereference but without allocating space for a elsewhere.
int b = #a; // Or something along those lines
a = 1;
b += 1;
assert(a==2);
August 13, 2021
On Fri, Aug 13, 2021 at 05:11:50PM +0000, Rekel via Digitalmars-d-learn wrote: [...]
> For anyone more experienced with C, I'm not well known with references but are those semantically similar to the idea of using a type at a predefined location?

References are essentially pointers under the hood. The difference is that at the language level they are treated as aliases to the original variable, and are therefore guaranteed to be non-null.

Note that in D `ref` is not a type constructor but a storage qualifier, so you cannot declare a reference variable, you can only get one if you pass a variable to a function that takes it by ref.


T

-- 
Spaghetti code may be tangly, but lasagna code is just cheesy.
August 13, 2021
On Friday, 13 August 2021 at 17:19:43 UTC, H. S. Teoh wrote:
> On Fri, Aug 13, 2021 at 05:11:50PM +0000, Rekel via Digitalmars-d-learn wrote: [...]
>> For anyone more experienced with C, I'm not well known with references but are those semantically similar to the idea of using a type at a predefined location?
>
> References are essentially pointers under the hood. The difference is that at the language level they are treated as aliases to the original variable, and are therefore guaranteed to be non-null.
>
> Note that in D `ref` is not a type constructor but a storage qualifier, so you cannot declare a reference variable, you can only get one if you pass a variable to a function that takes it by ref.
>
>
> T

Thanks for all the replies.

I had a look at emplace but it does not seem to do exactly what I have in mind.

What I had in mind would have the following behaviour. Suppose we optionally
allow "in <exp> before the semi-colon at the end of a declaration. With the following semantics

T x;
T y in &x;

assert(x==y);
assert(&x==&y);

Note that I am not suggesting that the syntax I wrote is what exists or should exist. I think what I am suggesting is not the same as say implicitly dereferenced pointers. If you think of the underlying machine, variables are aliases for locations in memory where values are stored, and what I am asking is whether it is possible to alias an arbitrary location (provided it contains the correct type.) (I guess what I am saying is only conceptually true variables might end up in registers, but from the point of view of the language it is true since if v is a variable, then &v is defined to be its address.)

This would allow things like:

Given:

struct S
{
   int x;
   int y;
}

You can write:

S s = S(1,2) in new S;

ending up with s being defined on the heap.

Anyway I hope it is clearer what I mean. Is it possible to do this in d?





August 13, 2021
On Friday, 13 August 2021 at 19:06:17 UTC, JG wrote:
> Anyway I hope it is clearer what I mean. Is it possible to do this in d?

union S
{
  int x;
  int a;
}

void main()
{
   S s= S(1234);

   writeln(s.a); //displays 1234
   s.x = s.x+1;
   writeln(s.a); //displays 1235
   s.a = s.a +1;
   writeln(s.a); //displays 1236
}

August 14, 2021
struct S {
  int x = 1234;
}

void main() {
  import std.stdio;
   S s;
   //construction of a using &(s.x)
   auto a = Ref!(int)(&s.x);
   writeln(a); //displays 1234
   s.x += 1;
   writeln(a); //displays 1235
   a += 1;
   writeln(s.x); //displays 1236
}

struct Ref(T) {
  T* ptr;
  this(T* p) { ptr = p; }
  string toString() { import std.conv; return to!string(*ptr); }
  ref T var() { return *ptr; }
  alias var this;
}
August 15, 2021

On Saturday, 14 August 2021 at 20:50:47 UTC, Carl Sturtivant wrote:

>
struct S {
  int x = 1234;
}

void main() {
  import std.stdio;
   S s;
   //construction of a using &(s.x)
   auto a = Ref!(int)(&s.x);
   writeln(a); //displays 1234
   s.x += 1;
   writeln(a); //displays 1235
   a += 1;
   writeln(s.x); //displays 1236
}

struct Ref(T) {
  T* ptr;
  this(T* p) { ptr = p; }
  string toString() { import std.conv; return to!string(*ptr); }
  ref T var() { return *ptr; }
  alias var this;
}

Hi,

This is exactly the behaviour I was trying to obtain.

It however comes with a fair amount of overhead, as can be seen in the following llvm ir:

define i32 @_Dmain({ i64, { i64, i8* }* } %unnamed) #0 {
  %s = alloca %onlineapp.S, align 4               ; [#uses = 4, size/byte = 4]
  %a = alloca %"onlineapp.Ref!int.Ref", align 8   ; [#uses = 5, size/byte = 8]
  %1 = bitcast %onlineapp.S* %s to i8*            ; [#uses = 1]
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %1, i8* align 1 bitcast (%onlineapp.S* @onlineapp.S.__init to i8*), i64 4, i1 false)
  %2 = bitcast %"onlineapp.Ref!int.Ref"* %a to i8* ; [#uses = 1]
  call void @llvm.memset.p0i8.i64(i8* align 1 %2, i8 0, i64 8, i1 false)
  %3 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, i32 0, i32 0 ; [#uses = 1, type = i32*]
  %4 = call %"onlineapp.Ref!int.Ref"* @pure nothrow ref @nogc @safe onlineapp.Ref!(int).Ref onlineapp.Ref!(int).Ref.__ctor(int*)(%"onlineapp.Ref!int.Ref"* nonnull returned %a, i32* %3) #4 ; [#uses = 0]
  %5 = load %"onlineapp.Ref!int.Ref", %"onlineapp.Ref!int.Ref"* %a, align 8 ; [#uses = 1]
  call void @@safe void std.stdio.writeln!(onlineapp.Ref!(int).Ref).writeln(onlineapp.Ref!(int).Ref)(%"onlineapp.Ref!int.Ref" %5) #4
  %6 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, i32 0, i32 0 ; [#uses = 2, type = i32*]
  %7 = load i32, i32* %6, align 4                 ; [#uses = 1]
  %8 = add i32 %7, 1                              ; [#uses = 1]
  store i32 %8, i32* %6, align 4
  %9 = load %"onlineapp.Ref!int.Ref", %"onlineapp.Ref!int.Ref"* %a, align 8 ; [#uses = 1]
  call void @@safe void std.stdio.writeln!(onlineapp.Ref!(int).Ref).writeln(onlineapp.Ref!(int).Ref)(%"onlineapp.Ref!int.Ref" %9) #4
  %10 = call i32* @pure nothrow ref @nogc @safe int onlineapp.Ref!(int).Ref.var()(%"onlineapp.Ref!int.Ref"* nonnull %a) #4 ; [#uses = 2]
  %11 = load i32, i32* %10, align 4               ; [#uses = 1]
  %12 = add i32 %11, 1                            ; [#uses = 1]
  store i32 %12, i32* %10, align 4
  %13 = getelementptr inbounds %onlineapp.S, %onlineapp.S* %s, i32 0, i32 0 ; [#uses = 1, type = i32*]
  %14 = load i32, i32* %13, align 4               ; [#uses = 1]
  call void @@safe void std.stdio.writeln!(int).writeln(int)(i32 %14) #4
  ret i32 0
}
« First   ‹ Prev
1 2