2015-11-07 37 views
1

是否有可能在编译时和运行时起作用的函数?在编译时和运行时起作用的函数

我想创建一个函数,它以一个任意的顺序接受整数和浮点数,然后逐个求和。

static template IsSame(T){ 
    static template As(alias t){ 
    enum As = is(T == typeof(t)); 
    } 
} 
template staticFold(alias Func, alias B,Ts...){ 
    static if(Ts.length == 0){ 
    alias staticFold = B; 
    } 
    else static if(Ts.length == 1){ 
    alias staticFold = Func!(B,Ts[0]); 
    } 
    else{ 
    alias staticFold = staticFold!(Func,Func!(B,Ts[0]),Ts[1..$]); 
    } 
} 
template Sum(alias A, alias B){ 
    alias Sum = AliasSeq!(A + B); 
} 

template SumIntFloat(Ts...){ 
    alias IntSum = staticFold!(Sum,0,Filter!(IsSame!int.As,Ts)); 
    alias FloatSum = staticFold!(Sum,0.0f,Filter!(IsSame!float.As,Ts)); 
} 

它很好用,但它似乎只在编译时工作。如果我想在运行时调用这个函数呢?

void SumIntFloatV2(Ts...)(Ts ts){ 
    alias Ints = Filter!(IsSame!int.As,ts); 
    foreach(i;Ints){ 
    writeln(i); 
    } 
} 

这也适用于并打印所有传递给该函数的整数。

但是,如果我尝试使用staticFold,它会失败。

void SumIntFloatV3(Ts...)(Ts ts){ 
    alias Ints  = Filter!(IsSame!int.As,ts); 
    alias IntSum = staticFold!(Sum,0,Ints); 
    writeln(Intsum); 
} 

实例函数调用:

SumIntFloatV3!(1,1.0,2,3,2.0,3.0); 
SumIntFloatV3!(1,1,2,3,1.0,2.0); 
+0

相关:http://stackoverflow.com/q/31781188/944911 – sigod

+0

什么是调用这些函数应该看起来像? –

+0

增加了两个示例函数调用 –

回答

2

只要写一个普通的功能。在编译时环境中调用时,将在编译时自动进行解释。

struct Answer { 
     int IntSum = 0; 
     float FloatSum = 0.0; 
} 
Answer SumIntFloatV4(Ts...)(Ts ts) { 
     Answer a; 
     foreach(t; ts) { 
       static if(is(typeof(t) == int)) 
         a.IntSum += t; 
       else static if(is(typeof(t) == float)) 
         a.FloatSum += t; 
     } 

     return a; 
} 

void main() { 
     // compile time 
     pragma(msg, SumIntFloatV4(1,1.0,2,3,2.0,3.0)); 
     pragma(msg, SumIntFloatV4(1,1,2,3,1.0,2.0)); 
     // runtime 
     import std.stdio; 
     writeln(SumIntFloatV4(1,1.0,2,3,2.0,3.0)); 
     writeln(SumIntFloatV4(1,1,2,3,1.0,2.0)); 
} 
+0

我知道你可以在编译时评估大多数函数,但这在我的情况下不起作用。我想利用D的类型系统来生成一个函数,它可以在运行时/编译时调用,但有一些细节如无序函数参数。 –

0

虽然我很感谢答案,但他们并不是我所期待的。

B fold(F,B,Ts...)(F f,B init, Ts ts){ 
    static if(ts.length == 0){ 
    return init; 
    } 
    else{ 
    return fold(f,f(init,ts[0]),ts[1..$]); 
    } 
} 
Tuple!(int,float) SumintFloatV3(Ts...)(Ts ts){ 
    int intSum = fold((int a, int b) => a + b,0,Filter!(IsSame!int.As,ts)); 
    float floatSum = fold((float a, float b) => a + b,0.0f,Filter!(IsSame!float.As,ts)); 
    return tuple(intSum,floatSum); 
} 

现在可以调用它像这样:

writeln(SumintFloatV3(1,2,3.0f,5.0f,3,4));