Is there an alternative to "__FUNCTION__" that gives the actual function symbol and not the name as a string?

Simon simon.vanbernem at yahoo.de
Sun Oct 24 14:05:35 UTC 2021


On Saturday, 23 October 2021 at 20:24:32 UTC, Tim wrote:
> import std.traits, std.stdio;
> string generateLogCode(alias func)()
> {
>     string code = "writeln(";
>     code ~= "\"" ~ fullyQualifiedName!func ~ "(\"";
>     foreach(i, param; ParameterIdentifierTuple!func)
>     {
>         if(i)
>             code ~= ", \", \"";
>         code ~= ", " ~ param;
>     }
>     code ~= ", \");\");";
>     return code;
> }
> enum OUTPUT_REPRO_CASE = q{
>     pragma(msg, generateLogCode!(__traits(parent, {}))());
>     mixin(generateLogCode!(__traits(parent, {}))());
> };
> void test(int a, int[] b)
> {
>     mixin(OUTPUT_REPRO_CASE);
> }
> void main()
> {
>     test(1, [2, 3]);
> }

That worked! I needed to modify it a bit, since there is the 
"execution_count_to_log_reproduction_on"-template parameterto the 
enum. If I try to use that inside the token string, it just says 
it can't find the identifier, so I had to inject some non-token 
string in the middle that plays nice with the token string, where 
I can actually reference the parameter.

For completeness, here is how the code looks like now (I am 
completely horrified by the result):

> string generate_call_to_log_reproduction(alias func)(){
>   string code = 
> "dlog(generate_reproduction_for_current_function_call!("~fullyQualifiedName!func~", [get_string_argument_list_of_function!([ParameterIdentifierTuple!(__traits(parent, {}))])])(context.temp_allocator";
> 
>   foreach(i, param; ParameterIdentifierTuple!func)
>     code ~= "," ~ param;
> 
>   code ~= "));";
>   return code;
> }
> 
> string generate_call_to_log_execution_count(alias func)(){
>   return "dlog(\""~fullyQualifiedName!(func)~" execution count: 
> %lld\", execution_count);";
> }
> 
> enum OUTPUT_REPRO_CASE(s64 
> execution_count_to_log_reproduction_on = -1) = q{
>   static s64 execution_count = 0;
>   
> if(context.settings.debug_.output_call_counts_for_reproducible_functions){
>     
> mixin(generate_call_to_log_execution_count!(__traits(parent, 
> {})));
>   }
> } ~ "if(execution_count == 
> "~execution_count_to_log_reproduction_on.stringof~")"~q{
>   {
>     mixin(generate_call_to_log_reproduction!(__traits(parent, 
> {}))());
>     trigger_breakpoint();
>   }
> 
>   execution_count++;
> };


and the usage just looks like this:

> void some_function(int a, int b){
>   mixin(OUTPUT_REPRO_CASE!());
>   return a + b;
> }

The "mixin(OUTPUT_REPRO_CASE!());" then expands to:

> static s64 execution_count = 0;
> if(context.settings.debug_.output_call_counts_for_reproducible_functions){
>   mixin(generate_call_to_log_execution_count!(__traits(parent, 
> {})));
> }
> 
> if(execution_count == -1L){
>   mixin(generate_call_to_log_reproduction!(__traits(parent, 
> {}))());
>   trigger_breakpoint();
> }
> 
> execution_count++;


Thanks for your help!!!


More information about the Digitalmars-d-learn mailing list