我一直在阅读D语言中的模板系统,并发现了一个不寻常的结构,static if
。
从我设法掌握的内容来看,它是在编译时进行评估的,但是根据我搜索的内容,显示的here示例并没有给我带来启发。
template Factorial(ulong n)
{
static if(n < 2)
const Factorial = 1;
else
const Factorial = n * Factorial!(n - 1);
}
static if
做了什么,我何时应该使用它?
答案 0 :(得分:13)
D static if
是“条件编译”的基础,并且在编写关于代码变体的编译时决定的任何地方都起着重要的作用。
由于D没有预处理器,比如
#ifdef xxx
compile_this_piece_of_code
#endif
可以成为
static if(xxx)
{
compile_this_pece_of_code
}
类似地,元编程也可以通过静态if:
发生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
}
答案 1 :(得分:4)
维基百科的例子实际上非常简单:
template Factorial(ulong n)
{
static if(n < 2)
const Factorial = 1;
else
const Factorial = n * Factorial!(n - 1);
}
这是一个同名的模板(参见下面的Jonathan的评论)。 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和“normal”如果有不同的语义。 static if
接受在编译时评估的赋值表达式(http://dlang.org/version.html,“静态If”部分),而正常则接受在运行时计算的表达式。
Static if
只是进行Emilio提到的“条件编译”的一种方式。 D还有version
个关键字。所以Emilio的第一个条件编译示例(在D中不起作用)就像是:
version (XXX) {
// XXX defined
} else {
// XXX not defined
}
如果你想使用静态if,你会写一些类似的东西:
enum int XXX = 10;
static if (XXX == 10) {
pragma(msg, "ten");
}
答案 2 :(得分:3)
Andrei Alexandrescu有一个很好的演讲,你可以在这里看到静态,如果在C ++环境下(如果这是你的要求)。
链接:http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Static-If-I-Had-a-Hammer
简短回答 - 它使某些模板元编程的语法更加直观。
答案 3 :(得分:0)
Andrei Alexandrescu最近一直致力于巧妙地使用static if
&#34; Design by Introspection&#34;,并提供一些很好的例子(video,slides)。
他演讲中的直接示例是使用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;
}
}
}