Re: forward tuple arg to local variable + dtor

2022-01-22 Thread vit via Digitalmars-d-learn
On Saturday, 22 January 2022 at 19:01:09 UTC, Stanislav Blinov 
wrote:

On Saturday, 22 January 2022 at 18:00:58 UTC, vit wrote:


[...]


Take by value and make a copy without forwarding:

```d
import std.typecons : Tuple;
import std.meta : allSatisfy;

[...]


Thanks, second options is what I need. (In my case forwarding is 
more complex because weak ptrs need lock()).





Re: forward tuple arg to local variable + dtor

2022-01-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 22 January 2022 at 18:00:58 UTC, vit wrote:


I want implement something like this:


Scratch the previous reply, 'twas a brain fart... Simply take by 
value, no need for extra copies at all in that case. Arguments 
themselves will become those copies as needed.


```d
import std.meta : allSatisfy;

enum bool isRcPtr(T) = is(T == RcPtr!U, U);

//@safe access to data of multiple ref counted objects:
public auto apply(alias fn, Args...)(Args args)
if (allSatisfy!(isRcPtr, Args)) {

@property auto ref elm(alias param)()@trusted{
return param.get();
}

return fn(staticMap!(elm, args));
}
```


Re: forward tuple arg to local variable + dtor

2022-01-22 Thread Stanislav Blinov via Digitalmars-d-learn

On Saturday, 22 January 2022 at 18:00:58 UTC, vit wrote:


I want implement something like this:
...


Take by value and make a copy without forwarding:

```d
import std.typecons : Tuple;
import std.meta : allSatisfy;

enum bool isRcPtr(T) = is(T == RcPtr!U, U);

//@safe access to data of multiple ref counted objects:
public auto apply(alias fn, Args...)(Args args)
if (allSatisfy!(isRcPtr, Args)) {

Tuple!Args params = args; // borrow all

@property auto ref elm(alias param)()@trusted{
return param.get();
}

return fn(staticMap!(elm, args)); // staticMap over original 
args tuple

}
```

Or make a helper function that takes by value and forward to that:

```d
template apply(alias fn)
{
private auto impl(Args...)(Args args)
{
@property auto ref elm(alias param)()@trusted{
return param.get();
}
return fn(staticMap!(elm, args));
}

auto apply(Args...)(auto ref Args args)
if (allSatisfy!(isRcPtr, Args))
{
import core.lifetime : forward;
return impl(forward!args); // impl takes by value - 
RcPtrs passed by reference will be copied

}
}
```


Re: forward tuple arg to local variable + dtor

2022-01-22 Thread vit via Digitalmars-d-learn

On Saturday, 22 January 2022 at 17:23:12 UTC, Ali Çehreli wrote:

On 1/22/22 07:17, vit wrote:

> Why local variable of type tuple call destructors immediately
after
> initialization?

I don't even understand where the local variable comes from. If 
you want a pair of Foo objects, I would use std.typeconst.Tuple.


Otherwise I would use AliasSeq as I understand it like the 
following:


alias tup = AliasSeq!(Foo, Foo);

static foreach(Type; tup) {{
  Type x;
  writeln("check(", x.i, "): ", cast(void*));
}}

So, to me, AliasSeq!(Foo, Foo) is just a pair of types. I 
instantiate an object for each type individually and use it 
inside.


Ali


I want implement something like this:

```d
import std.stdio : writeln;
import std.meta : AliasSeq, staticMap;
import core.memory : pureMalloc, pureFree;
import core.lifetime : emplace, forward;


void main()@safe{
auto rc1 = RcPtr!int.make(1);   //ref counted pointer

long result = 0;

//apply can be @safe
apply!((ref int a, ref long b){
rc1 = null;	//apply has copy of rc1, a is not 
dangling reference

result = a + b;

})(rc1, RcPtr!long.make(2));

assert(result == 3);
}

//@safe access to data of multiple ref counted objects:
public auto apply(alias fn, Args...)(scope auto ref Args 
args){
	Args params = forward!args;	//copy lvalue and move rvalue 
args


@property auto ref elm(alias param)()@trusted{
return param.get();
}

return fn(staticMap!(elm, params));

}

//simple implementation of ref counted pointer
struct RcPtr(T){

private Payload* payload;

private this(Payload* payload)@safe{
this.payload = payload;
}

//copy ctor
public this(ref typeof(this) rhs){
this.payload = rhs.payload;
if(payload)
payload.count += 1;
}

//make data
public static auto make(Args...)(auto ref Args args){
Payload* payload = ()@trusted{
return cast(Payload*)pureMalloc(Payload.sizeof);
}();
emplace(payload, forward!args);
return RcPtr(payload);  
}

public ~this(){
this.opAssign(null);
}

//release payload
void opAssign(typeof(null) nil){
if(payload){
payload.count -= 1;
if(payload.count == 0){
destroy(*payload);
()@trusted{
pureFree(payload);
}();
payload = null;
}
}
}

//
ref T get()@system{
assert(payload);
return payload.data;
}

private struct Payload{
int count = 1;
T data;

this(Args...)(auto ref Args args){
data = T(forward!args);
}
}
}



```


Re: forward tuple arg to local variable + dtor

2022-01-22 Thread Ali Çehreli via Digitalmars-d-learn

On 1/22/22 07:17, vit wrote:

> Why local variable of type tuple call destructors immediately after
> initialization?

I don't even understand where the local variable comes from. If you want 
a pair of Foo objects, I would use std.typeconst.Tuple.


Otherwise I would use AliasSeq as I understand it like the following:

alias tup = AliasSeq!(Foo, Foo);

static foreach(Type; tup) {{
  Type x;
  writeln("check(", x.i, "): ", cast(void*));
}}

So, to me, AliasSeq!(Foo, Foo) is just a pair of types. I instantiate an 
object for each type individually and use it inside.


Ali



Re: forward tuple arg to local variable + dtor

2022-01-22 Thread vit via Digitalmars-d-learn

On Saturday, 22 January 2022 at 14:23:32 UTC, Adam Ruppe wrote:
You can't forward to a local variable. Local variables will be 
a copy of the tuple. forward only actually works if sent 
*directly* to another function call.


There's a bunch of things in D that only work in function 
parameter lists and not local variables. This is one of them.


Thanks,
Why local variable of type tuple call destructors immediately 
after initialization?


```d
import std.stdio : writeln;
import std.meta : AliasSeq;

struct Foo{
int i;

this(int i){
this.i = i;
writeln("ctor(", i, "): ", cast(void*));
}

~this(){
writeln("dtor(", i, "): ", cast(void*));
i *= -1;
}
}


void main(){
{
AliasSeq!(Foo, Foo) tup;

static foreach(alias x; tup)
writeln("check(", x.i, "): ", cast(void*));	//x is 
destructed

}
}

```

Print:
```
dtor(0): 7FFF30D76868
dtor(0): 7FFF30D76858
check(0): 7FFF30D76858 //dangling?
check(0): 7FFF30D76868 //dangling?
```



Re: forward tuple arg to local variable + dtor

2022-01-22 Thread Adam Ruppe via Digitalmars-d-learn
You can't forward to a local variable. Local variables will be a 
copy of the tuple. forward only actually works if sent *directly* 
to another function call.


There's a bunch of things in D that only work in function 
parameter lists and not local variables. This is one of them.