How to pass alias as template parameter?
Everlast
Everlast at For.Ever
Mon Aug 27 18:16:29 UTC 2018
On Monday, 27 August 2018 at 09:50:01 UTC, Andrey wrote:
> Hello,
> This code doesn't compile:
>
> -----------------------------------------------------------------------
> import std.meta;
> import std.stdio;
>
> enum Option : string
> {
> First = "-first" ,
> Second = "-second",
> Qwerty = "-qwerty"
> }
>
> void handler(Option option)(string[] args, ref ushort index)
> {
> writeln("Case: ", args[index]);
> }
>
> void handler(string arg, ref ushort index)
> {
> writeln("Default: ", arg, " at index ", index);
> }
>
// Multiple issues here.
for example, you call handler but it means nothing at compile
time(the writeln should give that away)
// You seem to think AliasSeq is a list/array when it is slightly
different, nesting AliasSeq's do not produce a nested
array(unfortunately, although it shouldn't be difficult to
implement such a thing.
> alias Pair(alias key, alias value) = AliasSeq!(key, value);
> alias Pairs = AliasSeq!(Pair!(Option.First,
> handler!(Option.First)), Pair!(Option.Second,
> handler!(Option.Second)), handler);
>
> void parseArgs(alias sequence)(ushort index, string[] args)
> {
> alias last = sequence[$ - 1];
> alias pairs = sequence[0 .. $ - 2];
>
> for(ushort i = index; i < args.length; ++i)
> {
> string arg = args[i];
> switch(arg)
> {
> static foreach(pair; pairs)
> {
> case pair.key:
> pair.value(args, i);
> break;
> }
>
> default:
> last(arg, i);
> break;
> }
> }
> }
>
> void main()
> {
// These are run time variables, that is, the compiler does
not know about them at compile time, hence you cannot use them
for compile time parameters(Template parameters)
> ushort index = 1;
> string[] args = ["-second", "123", "-qaz", "true",
> "-first", "77", "value"];
// This makes no sense, the only sense it could make is
that you mean
parseArgs!(Pairs(index, args));
but index and args are runtime. If you convert them to
compile time using enum then they can be passed, but Pairs is
still malformed as is parseArgs.
> parseArgs!Pairs(index, args);
> }
> -----------------------------------------------------------------------
>
> Output:
>>onlineapp.d(52): Error: template instance `parseArgs!("-first",
>>handler, "-second", handler, handler)` does not match template
>>declaration parseArgs(alias sequence)(ushort index, string[]
>>args)
>
> I don't understand how to pass my "Pairs" alias into template
> function "parseArgs".
>
> P.S. Yes, I know that exists "getopt".
None of that code really makes any sense. Do you have any idea
what you are actually doing?
Better for you to use getopt until you learn what you are trying
to do.
Basically the code is so malformed in the use of meta programming
that it really does not make a lot of sense.
This is what you should do:
1. Write all your code without templates, don't think of meta
programming!
2. Your code then will work fine with CTFE and will be optimized.
e.g., suppose you have
ushort index = 1;
string[] args = ["-second", "123", "-qaz", "true", "-first",
"77", value"];
parseArgs(index, args);
Then by changing those types to enum the compiler will
automatically evaluate the code at compile time for you! no meta
programming involved(except the use of enum).
This is actually what you need to do because using arguments is a
runtime thing... if you wrote your code to take compile time
arguments you can only use them at compile time, defeating the
whole purpose.
Your mind has not learned to divide the compile time meta
programming with the runtime programming and so it looks like you
are mixing the two, and they can never be mixed up! Except that
runtime can be executed at compile time using a "trick"(CTFE)
which can make life very easy.
In fact, you always want to try to do everything as if it were
runtime because you can almost always use it at compile time
using CTFE. So you cover much more area than think you do.
Then, naturally, you will want to make the compile time version
behave a little different and you will use a little meta
programming, but naturally instead of trying to force it.
Then you will develop a better understanding of the meta side of
programming, which is just really about making really efficient
code by doing things at compile time that can be done there(such
as precomputing values(which CTFE generally covers well),
reducing code bloat by working in more generic type space(e.g.,
overloading is a form of meta programming), etc..)
One of the bad things about D is that it's error messages in meta
code can be total gibberish, so it is not a good idea to over
complicate things. You also cannot debug the meta code nor debug
string mixins and so you'll end up wasting a lot of time and not
get very far.
Basically you shouldn't be trying to force anything to be meta in
D, It will generally naturally fall out of a problem after you
realize you can generalize something and then you generalize the
specific runtime code you already have.
More information about the Digitalmars-d-learn
mailing list