On Monday, 25 June 2018 at 10:49:26 UTC, Simen Kjærås wrote:
On Monday, 25 June 2018 at 09:36:45 UTC, Martin Tschierschke
wrote:
I am not sure that I understood it right, but there is a way
to detect the status of a parameter:
My question was different, but I wished to get a ctRegex! or
regex used depending on the expression:
import std.regex:replaceAll,ctRegex,regex;
auto reg(alias var)(){
static if (__traits(compiles, {enum ctfeFmt = var;}) ){
// "Promotion" to compile time value
enum ctfeReg = var ;
pragma(msg, "ctRegex used");
return(ctRegex!ctfeReg);
}else{
return(regex(var));
pragma(msg,"regex used");
}
}
}
So now I can always use reg!("....") and let the compiler
decide.
To speed up compilation I made an additional switch, that when
using DMD (for development)
alway the runtime version is used.
The trick is to use the alias var in the declaration and check
if it can be assigned to enum.
The only thing is now, that you now always use the !() compile
time parameter to call the function. Even, when in the end is
translated to an runtime call.
reg!("....") and not reg("...").
Now try reg!("prefix" ~ var) or reg!(func(var)). This works in
some limited cases, but falls apart when you try something more
involved. It can sorta be coerced into working by passing
lambdas:
template ctfe(T...) if (T.length == 1) {
import std.traits : isCallable;
static if (isCallable!(T[0])) {
static if (is(typeof({enum a = T[0]();}))) {
enum ctfe = T[0]();
} else {
alias ctfe = T[0];
}
} else {
static if (is(typeof({enum a = T[0];}))) {
enum ctfe = T[0];
} else {
alias ctfe = T[0];
}
}
}
string fun(string s) { return s; }
unittest {
auto a = ctfe!"a";
string b = "a";
auto c = ctfe!"b";
auto d = ctfe!("a" ~ b); // Error: variable b cannot be
read at compile time
auto e = ctfe!(() => "a" ~ b);
auto f = ctfe!(fun(b)); // Error: variable b cannot be read
at compile time
auto g = ctfe!(() => fun(b));
}
--
Simen
This doesn't work, the delegate only hides the error until you
call it.
auto also does not detect enum. Ideally it should be a manifest
constant if precomputed... this allows chaining of optimizations.
auto x = 3;
auto y = foo(x);
the compiler realizes x is an enum int and then it can also
precompute foo(x).
Since it converts to a runtime type immediately it prevents any
optimizations and template tricks.