8

我一直在阅读 D 语言中的模板系统,并遇到了一个不寻常的结构,static if.

从我设法掌握的情况来看,它是在编译时进行评估的,但从我搜索的内容来看,这里显示的示例并没有给我很大启发。

template Factorial(ulong n)
{
    static if(n < 2)
        const Factorial = 1;
    else
        const Factorial = n * Factorial!(n - 1);
}

有什么作用static if,我应该什么时候使用它?

4

4 回答 4

13

Dstatic if是“条件编译”的基础,在必须对代码变体做出编译时决定的任何地方都起着重要作用。

由于 D 没有预处理器,因此

#ifdef xxx
compile_this_piece_of_code
#endif

可以变成

static if(xxx)
{
     compile_this_pece_of_code
}

同样,元编程也可以通过静态发生,如果:

template<int x>
struct traits
{ some definition calculated from x };

template<>
struct traits<0>
{ same definitions for the 0 particular case }

template(int x)
{
    static if(x==0)
    { some definitions }
    else
    { some other same definitions }
    even more definition common in the two cases
}
于 2012-09-11T12:54:56.173 回答
4

维基百科的例子其实很简单:

template Factorial(ulong n)
{
    static if(n < 2)
        const Factorial = 1;
    else
        const Factorial = n * Factorial!(n - 1);
}

它是一个同名模板(参见下面乔纳森的评论)。n是模板参数。所以,如果你改为写:

template Factorial(ulong n)
{
    if(n < 2) // NOTE: no static here
        const Factorial = 1;
    else
        const Factorial = n * Factorial!(n - 1);
}

? - 不起作用。检查http://dpaste.dzfl.pl/3fe074f2。原因是静态 if 和“正常” if 具有不同的语义。采用在编译时static if评估的赋值表达式(http://dlang.org/version.html,“Static If”部分),而普通 if 采用在运行时评估的表达式。

Static if只是执行 Emilio 提到的“条件编译”的一种方法。D 也有version关键字。所以 Emilio 的第一个条件编译示例(在 D 中不起作用)变成了这样:

version (XXX) { 
    // XXX defined 
} else { 
    // XXX not defined 
}

如果您想为此使用 static if,您可以编写如下内容:

enum int XXX = 10;
static if (XXX == 10) {
    pragma(msg, "ten");
}
于 2012-09-11T13:03:15.567 回答
3

Andrei Alexandrescu 有一个很好的演讲,如果在 C++ 上下文中,你可以在这里观看关于静态的演讲(如果这是你所要求的)。

链接:http ://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Static-If-I-Had-a-Hammer

简短的回答——它使某些模板元编程的语法更加直观。

于 2012-09-11T15:03:48.733 回答
0

Andrei Alexandrescu 最近static if通过一些很好的例子(视频幻灯片)呼吁巧妙地使用“内省设计”。

他的演讲中的一个直接示例是实现一个通用容器,例如使用 Robin Hood 哈希的哈希表,其中与表中的每个条目一起保存一个额外的数据(探测计数)。我们可以通过static if根据对齐方式将探测计数放在键旁边来自动优化内存,优化索引类型的整数宽度等。

从谈话中转述:

struct RobinHashTable(K, V, size_t maxLength) {
  static if (maxLength < ushort.max-1) {
    alias CellIdx = ushort;
  } else {
    alias CellIdx = uint;
  }

  static if (K.sizeof % 8 < 7) {
    align(8) struct KV {
      align(1):
        K k;
        ubyte cellData;
      align(8):
        V v;
    }
  } else {
    align(8) struct KV {
      align(8):
        K k;
        V v;
      align(1):
        ubyte cellData;
    }
  }
}
于 2017-08-01T09:30:30.243 回答