Aliasing a mixin (or alternative ways to profile a scope)

Johannes Loher johannesloher at fg4f.de
Thu Mar 7 20:34:48 UTC 2019


Am 07.03.19 um 21:07 schrieb Simon:
> Hello,
> 
> I am currently porting the frontend of my instrumenting profiler to D.
> It features a C++-makro that profiles the time between entering and
> leaving a scope (achieved with con-/destructors in C++). Since D has
> scopeguards, I hoped to achieve this by creating a mixin that generates
> the following code:
> 
> measure("func1");
> scope(exit) measure("func1");
> 
> Since I of course don't want to type a mixin for that everytime I want
> to use it, I tried to alias it:
> 
> import std.meta : Alias;
> alias profile_scope(string name) = Alias!(mixin("measure(\"" ~ name ~
> "\"); scope(exit) measure(\"" ~ name ~ "\");"));
> 
> I expected this to generate the code above by typing
> profile_scope("func1") in my programm. However the compiler (dmd) gives
> me the following error:
> 
> source\main.d(24): Error: template plattform.profile_scope cannot deduce
> function from argument types !()(string), candidates are:
> source\plattform.d(262):        plattform.profile_scope(string name)
> 
> This looks like a deduction/overload kind of error, which has me
> completly confused since there is no other identifier of the name
> "profile_scope" in my programm and the error message shows only one
> candidate.
> 
> Is there any way I can achive generating those two statements using only
> something that effectively looks like a function call/C-macro with an
> argument?
The error you are seeing is due to the fact that you pass "func1" as
runtime parameter instead of as a teamplate parameter. You would need to
do `profile_scope!("func1");`. However, this will still not work and
you'll get an error message similar to this:
```
main.d(4): Error: incomplete mixin expression writeln("func1");
scope(exit) writeln("func1");
main.d(8): Error: template instance `main.profile_scope!"func1"` error
instantiating
```

The underlying problem is that you can only alias expressions, i.e. you
cannot use alias to generate macro like functionality.

`measure("func1"); scope(exit) measure("func1");` is not an expression,
it is simply a statement, so the alias cannot work.

If you want to inject code directly at some place, basically your only
option is to use a string mixin. I understand that you do not want to
write `mixin` all the time, but to me, this does not look that bad:
```
auto profile_scope(string name)
{
    import std.format : format;
    return q{import std.stdio : writeln; writeln("%1$s"); scope(exit)
writeln("%1$s");}.format(name);
}

void main()
{
    mixin(profile_scope("func1"));
}
```
(replace writeln with your appropriate function call, "measure" in your
example).



More information about the Digitalmars-d-learn mailing list