Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are variadic mixin templates possible in D?

Suppose I need to do something similar to this:

mixin(some_template!("x", "foo"));

mixin(some_template!("x", "bar"));

mixin(some_template!("x", "baz"));

mixin(some_template!("y", "foo"));

mixin(some_template!("y", "bar"));

mixin(some_template!("z", "baz"));

Is it somehow possible to create another_template which is a variadic version of some_template, where you can give anywhere from 2 to however-many arguments? What I mean is that I would like to be able to say:

mixin(another_template!("x", "foo", "bar", "baz"));

mixin(another_template!("y", "foo", "bar"));

mixin(another_template!("z", "baz"));

and have it expand to equivalent code to what the first example would expand to.

like image 575
Koz Ross Avatar asked Dec 15 '22 18:12

Koz Ross


1 Answers

Yes, using the regular variadic template syntax (Something... collects the rest of the template arguments given and they can be of mixed types. see: http://dlang.org/template#TemplateTupleParameter):

string some_template(strings...)() {
        string a;
        foreach(f; strings)
                a ~= f;
        return a;
}

void main() {
        mixin(some_template!("int ", "giggle", ";"));
}

You can restrict the type with a constraint like this:

// this condition will only compile if it is passed a string
import std.typetuple;
enum check_if_string(string s) = true;

// then we check that they all compile with the check_if_string check
string some_template(strings...)() if(allSatisfy!(check_if_string, strings)) {
        string a;
        foreach(f; strings)
                a ~= f;
        return a;
}

The error message will be ugly though, and non-strings won't compile even without this check so it isn't really important. But you can also use the if check in there for like if(strings.length >= 2) as well.

This is called a template constraint: http://dlang.org/template#Constraint

like image 106
Adam D. Ruppe Avatar answered Dec 17 '22 07:12

Adam D. Ruppe