Templates D如何允许代理作为模板参数?

Templates D如何允许代理作为模板参数?,templates,delegates,d,stack-frame,Templates,Delegates,D,Stack Frame,在Andrei Alexandrescu的“D编程语言”中 有一个将委托作为模板参数的示例: T[]查找(别名pred,T)(T[]输入) if(is(typeof(pred(输入[0])==bool)) { 对于(;input.length>0;input=input[1..$]){ if(pred(输入[0])中断; } 返回输入; } 单元测试{ int[]a=[1,2,3,4,-5,3,-4]; int z=-2; 自动b=find!(委托(x){returnx

在Andrei Alexandrescu的“D编程语言”中

有一个将委托作为模板参数的示例:

T[]查找(别名pred,T)(T[]输入)
if(is(typeof(pred(输入[0])==bool))
{
对于(;input.length>0;input=input[1..$]){
if(pred(输入[0])中断;
}
返回输入;
}
单元测试{
int[]a=[1,2,3,4,-5,3,-4];
int z=-2;
自动b=find!(委托(x){returnx
Alexandrescu解释说,这是因为委托实际上是一个胖指针,由两部分组成:函数指针和指向其堆栈框架的指针(这就是为什么z可以在其主体内访问)。除了find将“pred”作为模板参数,而不是参数。模板参数只能是编译时常量

我确信在我们的单元测试中匿名委托的地址确实是一个编译时常量,但是它的堆栈帧的地址当然不应该是,那么如何将委托作为模板参数呢


这到底是怎么回事?

alias参数会生成为给定的特定符号定制的新代码,其中包括上下文中的内容

让我们看一下拆解:

0805c850 <_D6test564mainFZv20__T12__dgliteral1TiZ12__dgliteral1MFNbNfiZb>:
805c850:       55                      push   ebp
805c851:       8b ec                   mov    ebp,esp
805c853:       83 ec 04                sub    esp,0x4
805c856:       8b 48 d8                mov    ecx,DWORD PTR [eax-0x28]
805c859:       3b 4d 08                cmp    ecx,DWORD PTR [ebp+0x8]
805c85c:       0f 9f c0                setg   al
805c85f:       0f b6 c0                movzx  eax,al
805c862:       c9                      leave
805c863:       c2 04 00                ret    0x4
这就是
intz=-2行(-2在32位中表示为FFFFFFF E)。它像常规局部变量一样存储在堆栈中

底线是,特定的alias参数生成了一个全新的函数,它知道所有局部变量的位置。当它被调用时,指向它们的基指针被转发给它,这就是它所需要知道的

请注意,您也可以将局部变量作为别名参数传递,并获得类似的代码,它生成一个直接戳偏移量的函数,而不是使用指针

此外,如果尝试将运行时委托传递给alias参数,或者尝试将alias dg存储在其他位置,则不会编译。这是一个特殊的函数,带有特定于案例的代码,很多通用委托的东西都不适合它

0805c868 <_D6test5632__T4findS18main12__dgliteral1TiZ4findMFNaNbNfAiZAi>:
 // snip a bunch of irrelevant code
805c870:       89 45 fc                mov    DWORD PTR [ebp-0x4],eax
// snip
805c892:       8b 45 fc                mov    eax,DWORD PTR [ebp-0x4]
805c895:       89 95 f8 ff ff ff       mov    DWORD PTR [ebp-0x8],edx
805c89b:       e8 b0 ff ff ff          call   805c850 <_D6test564mainFZv20__T12__dgliteral1TiZ12__dgliteral1MFNbNfiZb>
 805c7da:       89 e8                   mov    eax,ebp
 805c7dc:       e8 87 00 00 00          call   805c868 <_D6test5632__T4findS18main12__dgliteral1TiZ4findMFNaNbNfAiZAi>
 805c7d1:       c7 45 d8 fe ff ff ff    mov    DWORD PTR [ebp-0x28],0xfffffffe