D函数模板与类型推理

D函数模板与类型推理,d,type-inference,function-templates,D,Type Inference,Function Templates,考虑以下代码: module ftwr; import std.regex; import std.stdio; import std.conv; import std.traits; S consume (S) (ref S data, Regex ! ( Unqual!(typeof(S.init[0])) ) rg) { writeln (typeid(Unqual!(typeof(S.init[0])))); auto m = match(data, rg);

考虑以下代码:

module ftwr;

import std.regex;
import std.stdio;
import std.conv;
import std.traits;

S consume (S) (ref S data, Regex ! ( Unqual!(typeof(S.init[0])) ) rg)
{
    writeln (typeid(Unqual!(typeof(S.init[0]))));

    auto m = match(data, rg);
    return m.hit;
}

void main()
{
    auto data = "binary large object";
    auto rx = regex(".*");
    consume (data, rx); // this line is mentioned in the error message
}
现在,我希望编译器推断
consume
将被实例化为

string consume!(string)(string, Regex!(char))
但这似乎没有发生。错误如下:

func_template_with_regex.d(24): Error: template ftwr.consume(S) does not match any function template declaration
func_template_with_regex.d(24): Error: template ftwr.consume(S) cannot deduce template function from argument types !()(string,Regex!(char))
我发现参数类型是正确的。。。我尝试过函数签名的一些变体,如:

S consume (S) (Regex ! ( Unqual!(typeof(S.init[0])) ) rg, ref S data)
它也不会编译(其目的是改变参数的顺序),并且

它编译并推断了这些类型。如果我在调用中显式指定类型,即

consume!string(data, rx);
它还编译和调试
writeln
打印
char
,正如预期的那样。我是在推理规则中遗漏了什么,还是刚刚在编译器中遇到了一个bug

哦,是的:

$ dmd -v
DMD64 D Compiler v2.053
...

我不能说这是否是一个bug,但这里有一个解决方法,它不会强迫您指定类型或更改参数的顺序。将
消费
的签名更改为:

S consume (S, U) (ref S data, Regex!U rg) if (is(U == Unqual!(typeof(S.init[0]))))

这可能是因为它不能从第二个参数中推断出任何东西(太复杂了),所以它就是不能推断。@Mehrdad:我把“类型推断”想象成求解某个方程组的过程。如果它是正确的(?),那么,任何“过于复杂而无法推理的类型”都只是一个数据不足的方程。但看起来这个系统是可以解决的。。。(我这样认为是因为那里有一个直接的
S数据
,这就是解决方案本身)好吧,它不像计算机可以用代数方法解决任何方程组,所以这里可能也是同样的问题。也就是说,我并不是说不可能针对这种情况进行优化——这是完全可能的。这基本上就是我要说的,尽管添加
是someString!S
到模板约束也是一个好主意。无论如何,在bugzilla(d.puremagic.com/issues)中报告这一特殊情况可能是值得的,因为这似乎是一个编译器类型推断可以改进的领域。但是,一个带有模板约束的更干净的函数签名可以很好地工作。哦,可以用
data[0]
代替
S.init[0]
来进一步清理约束。@Jonathan M Davis:
isSomeString!S
是我下一步要添加的内容,当整个内容编译完成后:)
S consume (S, U) (ref S data, Regex!U rg) if (is(U == Unqual!(typeof(S.init[0]))))