Variadic template parameters, refactor a long chain of static if's to 'functions'.
Adam D. Ruppe
destructionator at gmail.com
Tue Jun 11 13:22:26 UTC 2019
On Tuesday, 11 June 2019 at 09:26:56 UTC, realhet wrote:
> static bool processId(bool captureIntId, alias r, alias a)(){
> mixin("alias ta = typeof("~a.stringof~");");
As I have been saying a lot, mixin and stringof should almost
never be used together. You could write this a lot easier:
alias ta = typeof(a);
no need for mixin at all.
> Error: template instance processId!(true, id, _param_1)
> processId!(true, id, _param_1) is nested in both Args and btn
So Args is a runtime thing, but you are trying to use it in
compile time. The compiler can handle one layer of this - it
basically inlines a runtime function when you do that - but with
more layers it gets lost.
What you'll need to do is to kinda embrace this and have a helper
struct that returns the stuff by value. To avoid holding all the
possible types, pass what you want to it as type arguments inside
the function.
Check this out:
---
struct ID { int val; }
struct enabled { bool val; }
struct disabled { bool val; }
struct PossibleArguments(T...) {
this(Args...)(Args args) {
static foreach(arg; args) {{
enum idx = TindexOf!(typeof(arg));
static if(idx >= 0)
contents[idx] = arg;
else
static assert(0, "Unusable arg "
~ typeof(arg).stringof);
}}
}
private T contents;
private static int TindexOf(What)() {
static foreach(idx, t; T) {
// you could use your isSame here
static if(is(t == What))
return cast(int) idx;
}
return -1;
}
auto opDispatch(string n)() {
static foreach(idx, item; T)
if(item.stringof == n)
return contents[idx].val;
assert(0);
}
}
void btn(T...)(string params, T args) {
// here's the usage: list args I want to support as CT,
// then pass the other args as runtime
auto r = PossibleArguments!(
ID,
enabled
)(args);
import std.stdio;
writeln(r.opDispatch!"ID"); // or r.ID, but while
debugging it helps to explicitly all r.opDispatch so you get the
full error instead of "no such property"
writeln(r.enabled);
}
void main() {
// I enabled the first two, but not disabled, so this is
an error
//btn("ignored", ID(5), enabled(true), disabled(false));
// but this works
btn("ignored", ID(5), enabled(true));
// and it can be reordered/ignored/etc
btn("ignored", enabled(false));
}
---
So now you avoid the list of ifs thanks to that TindexOf helper
thing while still getting the helpful user error message, and the
opDispatch can make feel like you are accessing by name inside.
Extending it to other types is an exercise for you :)
Particularly, the event ones will need a different approach of
some sort.
I would suggest actually putting them in a wrapper struct so you
can still use this cool name trick.
But alternatively, you could special-case them in the two loops,
like always knowing void delegate() is going to be named onClick.
I can help you solve this later too if you wanna go that way, I
just g2g right now lol.
More information about the Digitalmars-d-learn
mailing list