tags:

views:

94

answers:

3

Hi, I've been playing around recently with the D language and I have a quick question about templates.

I'm inserting characters and strings into an existing string in code and came up with this function:

string insert(T)(string s1, T s2, uint position) {
    return s1[0 .. position] ~ s2 ~ s1[position .. $];
}

Now, I have several questions.

  1. Can I limit the types allowed for the s2 argument (I only want char, wchar, dchar, etc. and their respective array values)?

  2. Is there some way to define the template to automatically know to prepend if the position arg is 0? Something like this (which does not compile, but gives the general idea):

    string insert(T)(string s1, T s2, uint position) {
      static if (position == 0)
        return "" ~ s2 ~ s1;
      else
        return s1[0 .. position] ~ s2 ~ s1[position .. $];
    }
    

Thanks

A: 

As to 2, can't you just use a normal if statement?

Bernard
+4  A: 
  1. Yes - using either template parameter specialization or template constraints (equivalent of C++1x concepts).
  2. static if implies that the condition can be calculated at compile time. A function parameter can't be, so either use a regular if or make position a template parameter.
CyberShadow
How do you go about making 'position' a template parameter? Something like the following? string insert(T, uint Position)(...) { static if (Position == 0) ... else ... }
GKelly
Essentially, I'm looking for a way to avoid as much run-time decisions as possible here, so I'm trying to see if I can avoid a 'normal' if. To be honest, I'm just exploring the language, I'd normally be happy enough with the non-static if, but I'm just exploring what's possible.
GKelly
@ first question: Yes.
CyberShadow
+1  A: 

For 1, there are actually two places you can restrict the allowable types.

The first is before method selection. If a symbol resolves to multiple methods, the compiler will try to eliminate as many as it can before it has to try and decide which one to use. Template constraints (D2 only) and specialisation work at this phase. For example:

string insert(T)(string s1, T s2, uint position) if(isSomeChar!T) // D2 only

-or-

string insert(T : dchar)(string s1, T s2, uint position) // D1 or D2

The other is after method selection. This is where the compiler has already decided to use this specific method. You can do this with static asserts. Note that this doesn't cause the compiler to go "ooh; I should try looking for a different overload!"; it will simply give up.

string insert(T)(string s1, T s2, uint position)
{
    static if( !isSomeChar!(T) )
    {
        pragma(msg, "Error: insert(T): T must be a character type.");
        static assert(false);
    }
    ...
}

One other thing: as far as I am aware, you *cannot simply concatenate wchars and dchars into a string (which is an array of chars). You will first need to encode the character into a string. encode in the std.utf module should do the trick.

DK