在编译时和运行时工作的函数

时间:2015-11-07 22:29:46

标签: d

是否可以在编译时和运行时使用函数?

我想创建一个以任意顺序获取整数和浮点数的函数,并单独求它们。

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);

2 个答案:

答案 0 :(得分:3)

只需写一个普通的功能。在编译时上下文中调用时,它将在编译时自动解释。

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));
}

答案 1 :(得分:0)

虽然我很感激答案,但他们并不是我想要的。

example.com

现在可以这样称呼它:

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);
}