如何通过 D 中的 is 表达式获取 alias-this-struct 的模板参数?
How to get the template argument of an alias-this-struct via is-expression in D?
我在玩 alias this
,它可以模拟 D 中结构的继承。对于我最近启动的库,我还想提供通过 is
检测正确类型的特征模板-表达式。
这是我的类型层次结构。
struct R(X) {
S!X s;
alias s this;
this(X i) { s = i; }
}
struct S(X) {
T a;
alias T = X;
alias a this;
this(T t) { a = t; }
}
import std.stdio : writeln;
void main()
{
R!int r = 3;
S!int s = r;
int i = r;
writeln(r, " ", s, " ", i );
static assert( is(r.s.T) && is(typeof(r) : S!(r.s.T)) );
static assert( is(typeof(r) : R!X, X) );
static assert( is(typeof(r) : int) && is(typeof(r) : S!int) );
alias T = int;
static assert( is(typeof(r) : S!T) );
static assert(
is(typeof(r) : S!Q, int Q) ||
is(typeof(r) : S!Q, Q) ||
is(typeof(r) : S!Q, r.s.T Q) ||
is(typeof(r) : R!Q, int Q) ||
is(typeof(r) : R!Q, r.s.T Q)
);
}
我希望所有 static asserts
都为真,因此它能够通过模板特化来匹配通用模板参数。但实际上,最后一个static assert
是false
!这不仅仅是 rdmd
或 dmd
,还有 ldc2
。我想,我在这里做错了。
我的问题是,如何在不使用我示例中的别名 r.s.T
的情况下从类型 S!X
中正确提取通用模板参数 X
?我想通过 is
-expression.
这个问题专门针对 struct
。为了性能和编程经验,我不会使用 class 继承来代替 alias this
。我的结构将只是一个成员字段的小包装,其主要目的是重载某些运算符。
谢谢。
您需要使用 is
INSIDE static if
进行提取。
static if(is(typeof(r) == R!Q, Q))
pragma(msg, Q); // will print that int, you can just use Q as a type inside this branch
else
// not an instance of R
is(typeof(r) : R!Q, r.s.T Q) 表示 r 的类型隐式转换为 R!Q,其中 Q 是 int 类型的值。所以这就像 R!4 之类的东西。与前两行和第一行相同,他们正在寻找 Q 是一个值,而不是一个类型。只有第二项以正确的形式完全匹配它……我猜这不仅仅是因为编译器不够聪明,无法深入研究它。就像很多 is exprs 实际上在一个层次的 ask 中工作得最好——隐式转换或提取 args。在这里,它要求同时执行这两项操作,而且很可能是一个编译器错误/惰性实现。
我在玩 alias this
,它可以模拟 D 中结构的继承。对于我最近启动的库,我还想提供通过 is
检测正确类型的特征模板-表达式。
这是我的类型层次结构。
struct R(X) {
S!X s;
alias s this;
this(X i) { s = i; }
}
struct S(X) {
T a;
alias T = X;
alias a this;
this(T t) { a = t; }
}
import std.stdio : writeln;
void main()
{
R!int r = 3;
S!int s = r;
int i = r;
writeln(r, " ", s, " ", i );
static assert( is(r.s.T) && is(typeof(r) : S!(r.s.T)) );
static assert( is(typeof(r) : R!X, X) );
static assert( is(typeof(r) : int) && is(typeof(r) : S!int) );
alias T = int;
static assert( is(typeof(r) : S!T) );
static assert(
is(typeof(r) : S!Q, int Q) ||
is(typeof(r) : S!Q, Q) ||
is(typeof(r) : S!Q, r.s.T Q) ||
is(typeof(r) : R!Q, int Q) ||
is(typeof(r) : R!Q, r.s.T Q)
);
}
我希望所有 static asserts
都为真,因此它能够通过模板特化来匹配通用模板参数。但实际上,最后一个static assert
是false
!这不仅仅是 rdmd
或 dmd
,还有 ldc2
。我想,我在这里做错了。
我的问题是,如何在不使用我示例中的别名 r.s.T
的情况下从类型 S!X
中正确提取通用模板参数 X
?我想通过 is
-expression.
这个问题专门针对 struct
。为了性能和编程经验,我不会使用 class 继承来代替 alias this
。我的结构将只是一个成员字段的小包装,其主要目的是重载某些运算符。
谢谢。
您需要使用 is
INSIDE static if
进行提取。
static if(is(typeof(r) == R!Q, Q))
pragma(msg, Q); // will print that int, you can just use Q as a type inside this branch
else
// not an instance of R
is(typeof(r) : R!Q, r.s.T Q) 表示 r 的类型隐式转换为 R!Q,其中 Q 是 int 类型的值。所以这就像 R!4 之类的东西。与前两行和第一行相同,他们正在寻找 Q 是一个值,而不是一个类型。只有第二项以正确的形式完全匹配它……我猜这不仅仅是因为编译器不够聪明,无法深入研究它。就像很多 is exprs 实际上在一个层次的 ask 中工作得最好——隐式转换或提取 args。在这里,它要求同时执行这两项操作,而且很可能是一个编译器错误/惰性实现。