2015-11-07 34 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));