d转发元组到局部变量
原文
为什么params元组变量在构造后立即销毁?
为什么是check(-2)在dtor(2)后?
import std.stdio : writeln;
import core.lifetime : forward, move;
struct Foo{
int i;
this(int i){
this.i = i;
writeln("ctor(", i, "): ", cast(void*)&this);
}
~this(){
writeln("dtor(", i, "): ", cast(void*)&this);
i *= -1;
}
}
void seq(Args...)(auto ref Args args){
Args params = forward!args;//这里
writeln("初化");
alias foo = params[0];
writeln("check(", foo.i, "): ", cast(void*)&foo);
}
void main(){
writeln("Foo(1):");
{
auto foo = Foo(1);
writeln("check(", foo.i, "): ", cast(void*)&foo);
}
writeln("\nFoo(2):");
seq(Foo(2));
}
输出:
Foo(1):
ctor(1): 7FFEBCAF0538
check(1): 7FFEBCAF0538
dtor(1): 7FFEBCAF0538
Foo(2):
ctor(2): 7FFEBCAF0548
dtor(2): 7FFEBCAF04F0
params initialized
check(-2): 7FFEBCAF04F0
dtor(0): 7FFEBCAF0558
亚当:
不能转发到局部变量.局部变量将是元组的副本.转发仅在直接发送到另一个函数调用时才真正管用.
D中有很多东西只适用于函数参数列表而不是局部变量.这是其中之一.
vit:
谢谢,为什么元组类型的局部变量在初化后立即调用析构函数?
import std.stdio : writeln;
import std.meta : AliasSeq;
struct Foo{
int i;
this(int i){
this.i = i;
writeln("ctor(", i, "): ", cast(void*)&this);
}
~this(){
writeln("dtor(", i, "): ", cast(void*)&this);
i *= -1;
}
}
void main(){
{
AliasSeq!(Foo, Foo) tup;
static foreach(alias x; tup)
writeln("check(", x.i, "): ", cast(void*)&x); //x析构了.
}
}
输出:
dtor(0): 7FFF30D76868
dtor(0): 7FFF30D76858
check(0): 7FFF30D76858 //悬挂?
check(0): 7FFF30D76868 //悬挂?
我不明白局部变量的来源.如果想要一对Foo对象,我会用std.typeconst.Tuple.
否则我会使用AliasSeq,按我理解它如下所示:
alias tup = AliasSeq!(Foo, Foo);
static foreach(Type; tup) {{
Type x;
writeln("check(", x.i, "): ", cast(void*)&x);
}}
AliasSeq!(Foo, Foo)是一对类型,我单独为每种类型实例化一个对象并在内部使用它
我想这样:
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);
}
}
}
按值取并复制而不转发:
import std.typecons : Tuple;
import std.meta : allSatisfy;
enum bool isRcPtr(T) = is(T == RcPtr!U, U);
//@safe访问多引用计数对象数据
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));
// 静每一,每个元类型
}
或造按值获取并转发给它的辅助函数.
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 按值取- 复制按引用传递的RcPtrs
}//根本不必要.
}
只要按值计算,根本不需要额外副本.
import std.meta : allSatisfy;
enum bool isRcPtr(T) = is(T == RcPtr!U, U);
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));
}
浙公网安备 33010602011771号