Why use static if in D?

淺唱寂寞╮ 提交于 2020-01-03 08:22:11

问题


I have been reading about the template system in the D language and came upon a unusual construct, static if.

From what I managed to grasp it is evaluated at compile time, but from what I have searched, the example shown here did not quite enlighten me.

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

What does static if do, and when should I use it?


回答1:


the D static if is the base for "conditional compilation", and plays an important role wherever a compile time decision about a variant of a code must be taken.

Since D doesn't have a preprocessor, things like

#ifdef xxx
compile_this_piece_of_code
#endif

can become

static if(xxx)
{
     compile_this_pece_of_code
}

similarly, metaprogramming can happen also via static if:

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

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

can be

template(int x)
{
    static if(x==0)
    { some definitions }
    else
    { some other same definitions }
    even more definition common in the two cases
}



回答2:


The wikipedia example is actually pretty simple:

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

It is an eponymous template (See Jonathan's comment below). n is the template parameter. So, what if you instead wrote:

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

? - It will not work. Check http://dpaste.dzfl.pl/3fe074f2 . The reason is the fact that static if and "normal" if have different semantics. static if takes an assignment expression ( http://dlang.org/version.html , section "Static If") that is evaluated at compile time, while normal if takes an expression that is evaluated at run-time.

Static if is just one way to do the "conditional compilation" mentioned by Emilio. D also has the version keyword. So Emilio's first conditional compilation example (which does not work in D) becomes something like:

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

If you want to use static if for this, you would write something like:

enum int XXX = 10;
static if (XXX == 10) {
    pragma(msg, "ten");
}



回答3:


Andrei Alexandrescu has a good talk that you can watch here about static if in a C++ context (if that's what your asking for).

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

Short answer- it makes the syntax for some template metaprogramming a lot more intuitive.




回答4:


Andrei Alexandrescu has lately been calling smart use of static if "Design by Introspection", with some great examples (video, slides).

A direct example from his talk would be implementing a generic container such as a hash table using Robin Hood hashing, where an extra data (probe count) is kept with each entry in the table. With static if we can optimize memory automatically by placing the probe count next to the key based on its alignment, optimize integer width for the index type, etc.

Paraphrased from the talk:

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


来源:https://stackoverflow.com/questions/12369978/why-use-static-if-in-d

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!