On 3/2/18 8:49 PM, Jonathan Marler wrote:
On Saturday, 3 March 2018 at 00:20:14 UTC, H. S. Teoh wrote:
On Fri, Mar 02, 2018 at 11:51:08PM +0000, Jonathan Marler via
Digitalmars-d wrote:
[...]
Not true:
template counterexample(alias T) {}
int x;
string s;
alias U = counterexample!x; // OK
alias V = counterexample!1; // OK
alias W = counterexample!"yup"; // OK
alias X = counterexample!s; // OK
alias Z = counterexample!int; // NG
The last one fails because a value is expected, not a type.
If you *really* want to accept both values and types, `...` comes to
the rescue:
template rescue(T...) if (T.length == 1) {}
int x;
string s;
alias U = rescue!x; // OK
alias V = rescue!1; // OK
alias W = rescue!"yup"; // OK
alias X = rescue!s; // OK
alias Z = rescue!int; // OK!
T
Ah thank you...I guess I didn't realize that literals like 1 and "yup"
were considered "symbols" when it comes to alias template parameters.
Well, they aren't. But template alias is a bit of a mess when it comes
to the spec. It will accept anything except keywords AFAIK. Would be
nice if it just worked like the variadic version.
The variadic version is what is usually needed (you see a lot of
if(T.length == 1) in std.traits).
But, if you wanted to ensure values (which is more akin to your
proposal), you can do:
template rescue(alias val) if(!is(val)) // not a type
-Steve