Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use static if in D?

Tags:

templates

d

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?

like image 930
coredump Avatar asked Sep 11 '12 12:09

coredump


4 Answers

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
}
like image 69
Emilio Garavaglia Avatar answered Nov 13 '22 00:11

Emilio Garavaglia


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");
}
like image 27
DejanLekic Avatar answered Nov 13 '22 01:11

DejanLekic


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.

like image 32
Robert Mason Avatar answered Nov 12 '22 23:11

Robert Mason


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;
    }
  }
}
like image 1
orip Avatar answered Nov 13 '22 01:11

orip