mercredi 6 octobre 2021

Collect signatures of all methods calls of my class at compile time in C++

I have my class, lets say for example it is called Any. It has different templated methods.

My task (that I can't solve) is to tell at compile time what methods and with what arguments types it was called, list of all 100% such use cases.

Of course I need to collect such use cases only within single .cpp module if possible, because different modules are compiled separately hence can know about each other information shared only through interface (external symbols) which is not enough (I guess) for my task.

I can modify bodies of my methods in any way, for example I can add to all methods some compile time code that will collect information about theirs call. But this added code should be ommitted at runtime, not to cause any overhead.

To remind - I have templated methods, it means that methods can be called with some unknown/new user-defined types. I also want to record such cases.

Also some templated methods are overloaded operators like + or += so I want to collect them too.

Main problem that I'm facing is that at compile time I can't modify any global variable (or am I wrong?). Otherwise inside each method call I could add compile time code that adds method call signature to some global array.

So I need 1) called methods names 2) called methods signatures (type of arguments and template params).

Also, I don't need solution at runtime, because I need performance. Obviously at runtime I could add to some std::vector all signatures of used types through typeid(argument).name().

The result of collecting call information should contain something like type-list

TypeList<
   Method<Name<'a', 'd', 'd'>, Ret<std::string>, Args<int, bool>>,
   Method<Name<'m', 'u', 'l'>, Ret<char>, Args<UserClass, double, float>>
>

This type-list of course I need to be available to process at the very end of my .cpp module. It will be used to generate some runtime code. For example those called methods will contain some empty stub (call to some external function) and this stub's runtime body will be generated at the very end of .cpp module. So that these methods will adopt their runtime code to the way how they very actually called inside module.

There is of course possibility to do following thing - do first time runtime pass of whole program, collect some runtime information about signatures of methods usage. Then based on this information generate extra C++ code and add it to this .cpp module. One problem here is that at single runtime pass not all control paths may be reached.

Another option is to parse Clang's AST tree of the module on first pass and then generate extra code that will be added to module.

Those other options are possible but right now I want to get for myself an answer if this task is solveable by just single compile-time pass of whole module without extra external tools like generator of Clang's AST.

Does anyone know how to solve this?





Aucun commentaire:

Enregistrer un commentaire