Templates 在D(LDC2)中调用模板函数时,委托被推断为无效
我有一个自定义的Templates 在D(LDC2)中调用模板函数时,委托被推断为无效,templates,d,type-inference,Templates,D,Type Inference,我有一个自定义的选项类型,使用代数编写 struct None{}; struct Some(T){ T t; alias t this; T get(){ return t; } }; alias Option(T) = Algebraic!(Some!(T), None); Option!T some(T)(T t){ return Option!T(Some!T(t)); } Option!T none(T)(){ re
选项
类型,使用代数
编写
struct None{};
struct Some(T){
T t;
alias t this;
T get(){
return t;
}
};
alias Option(T) = Algebraic!(Some!(T), None);
Option!T some(T)(T t){
return Option!T(Some!T(t));
}
Option!T none(T)(){
return Option!T(None());
}
然后我尝试编写一些基本的便利函数:
T getValue(T,uint size)(VariantN!(size, Some!T, None) opt){
return opt.get!(Some!T).t;
}
bool isDefined(T, uint size)(VariantN!(size, Some!T, None) opt){
return opt.convertsTo!(Some!T);
}
A match(A,T,uint size)(VariantN!(size, Some!T, None) opt, A delegate(T) some, A delegate() none){
if(opt.isDefined!(T,size)){
return some(opt.getValue!(T,size));
}else{
return none();
}
}
调用match
时,编译器无法推断模板的正确参数:
Option!int test = some(1);
bool boolReturn = test.match((x) => false, () => true);
有误:
Error: template util.match cannot deduce function from argument types !()(VariantN!(4LU, Some!int, None), void, bool function() pure nothrow @nogc @safe), candidates are:
src/util.d(79,3): util.match(A, T, uint size)(VariantN!(size, Some!T, None) opt, A delegate(T) some, A delegate() none)
错误输出表明,match
(意思是bool delegate(int)
或(x)=>false
)的第二个参数被推断为void
。为什么?
此示例编译(都相同,但明确给出了x的类型):
如果委托中没有给出类型名称,则会将其作为模板(在错误消息中键入void),在实例化时,该模板将具有推断类型。。。。在这里,它希望被推断为类型T,它本身是一个基于参数的推断参数 问题是编译器试图推断(x)=>模板,同时推断函数调用,但不知道先做哪一个,所以看起来不够深入。如果你在任何一个地方明确提到它,它就会打破这个循环: //工作 bool boolReturn=test.match!(bool,int)((x)=>false,()=>true) 或 //工作 test.match((int x)=>false) 但我不确定如何自动完成。。。我试着用不同的安排将它们分离,但还没有成功 Phobos通常通过将代理作为
alias
template参数而不是运行时参数来解决这个问题。将签名更改为:
typeof(none()) match(alias some, alias none, T, uint size)(VariantN!(size, Some!T, None) opt) {
并将呼叫更改为:
bool boolReturn = test.match!((x) => false, () => true);
这是可以编译的,因为您将推理移动到了两个层:首先,编译器接受那些仍然以模板形式存在的委托作为参数。然后它接受test
,并计算出其类型以推断其他参数。然后它移动到主体中,实际看到对some
的调用,并在主体内的该点实例化其参数类型。它之所以有效,是因为推断类型是在从签名层(在主体外部)已知类型T之后完成的
但是如果不使用模板功能,那么。。。。我不知道,我认为解决方案是做两层,这样显式类型在其中一层命名,但我还没有弄清楚(tbh将停止尝试,因为我现在还有其他事情要做)。如果委托中没有给出类型名称,它将作为模板(在错误消息中键入void)当它被实例化时,它将具有一个推断类型。。。。在这里,它希望被推断为类型T,它本身是一个基于参数的推断参数 问题是编译器试图推断(x)=>模板,同时推断函数调用,但不知道先做哪一个,所以看起来不够深入。如果你在任何一个地方明确提到它,它就会打破这个循环: //工作 bool boolReturn=test.match!(bool,int)((x)=>false,()=>true) 或 //工作 test.match((int x)=>false) 但我不确定如何自动完成。。。我试着用不同的安排将它们分离,但还没有成功 Phobos通常通过将代理作为
alias
template参数而不是运行时参数来解决这个问题。将签名更改为:
typeof(none()) match(alias some, alias none, T, uint size)(VariantN!(size, Some!T, None) opt) {
并将呼叫更改为:
bool boolReturn = test.match!((x) => false, () => true);
这是可以编译的,因为您将推理移动到了两个层:首先,编译器接受那些仍然以模板形式存在的委托作为参数。然后它接受test
,并计算出其类型以推断其他参数。然后它移动到主体中,实际看到对some
的调用,并在主体内的该点实例化其参数类型。它之所以有效,是因为推断类型是在从签名层(在主体外部)已知类型T之后完成的
但是如果不使用模板功能,那么。。。。我不知道,我认为解决方案是做两层,这样显式类型在其中一层命名,但我还没有弄清楚(tbh将停止尝试,因为我现在还有其他事情要做)。两层方法很好地工作。感谢分享:)两层方法很好地工作。谢谢分享:)