On Sunday, 3 May 2015 at 21:46:11 UTC, Robert M. Münch wrote:
Hi, I have now played a around couple of hours (reading
everything I could find) to get something to work, but I think
I'm missing some basic concepts/understanding. Maybe someone
can enlighten me how these things work. I thought that some
code from David Nadlinger is what I'm searching for but don't
know how to exactly make use of it.
Here is the code: I want to filter out some of the "allMembers"
and use them in my code for a switch/final to check that call
cases that were not filtered are covered. Trying to build the
enum for the switch/final statement.
auto org_rules = TypeTuple!(__traits(allMembers,BolSource));
static assert(!isTypeTuple!(org_rules));
template startsNotWith(T,char C){
static if (T[0] != C){
enum startsNotWith = true;
} else {
enum startsNotWith = false;
}
}
Here T would have to be a type. But you want to accept a string.
So:
----
template startsNotWith(string s,char c){
enum startsNotWith = s.length == 0 || s[0] != c;
}
----
template StaticFilter(alias pred, T...) {
static if (T.length == 0) {
alias TypeTuple!() StaticFilter;
} else static if (pred!(T[0])) {
alias TypeTuple!(T[0], StaticFilter!(pred, T[1 .. $]))
StaticFilter;
} else {
alias StaticFilter!(pred, T[1 .. $]) StaticFilter;
}
}
alias startsNotWithp = startsNotWith!(T,"p"); // doesn't
compile: Error: undefined identifier T
You need to turn T into a parameter, so that StaticFilter can set
it. (And it's really a string again, so I'm renaming to s.)
----
template startsNotWithp(string s)
{
enum startsNotWithp = startsNotWith!(s, 'p');
}
/* Shorthand syntax: enum startsNotWithp(string s) =
startsNotWith!(s, 'p'); */
----
alias rules = StaticFilter!(startsNotWithp, org_rules);
While playing with this a couple of questions came up:
1. How do predicates get their argument(s)? I saw code where
only the predicate was mentioned but no arguments. So, I assume
there is some behind-the-curtain-magic going on. I read about
things like "a == b" where I can reference 'a and 'b in a
string.
Predicates are called/instantiated by the thing to which you pass
them. StaticFilter instantiates pred for each element of the T
tuple it's given. If some documentation doesn't say how the
predicate will be called/instantiated, then it's probably assumed
to be obvious.
String predicates are turned into functions behind the curtains.
The thing you instantiate with "a == b" turns it into `(a, b)
{return a == b;}` and uses that. I think we don't do string
predicates for templates like StaticFilter, though.
2. "enum startsNotwith = false" So this is the return syntax
for a CTFE for "return(true)" ?
It's the template syntax for "return false". CTFE does normal
functions at compile time, so there it's just "return false".
----
/* Template: */
template t() {enum t = false;}
enum x = t!();
/* CTFE: */
bool f() {return false;}
enum y = f();
----
3. TupleType is a very missleading name when you are learning
these things, because the tuple can hold values as well.
Yup. And std.traits.isTypeTuple only adds to the confusion.
Or is there a more extensive explanation for the name I don't
get?
Not that I'm aware of.
4. Are there any tutorials about CTFE? This seems to be a very
powerful but not so easy to use feature of D, but documentation
is quite limited.
CTFE is rather simple. It just allows you to use certain
functions in a static (i.e. compile time) context.
Templates are more tricky. If you mean templates, maybe having
the right name helps.