I have a function whose behavior may need to be modified based on the file it is called from (e.g., to increase debugging trace output). This modification would need to be done without recompiling (e.g., by editing a configuration file or changing an environment variable).
Just as an example that would fill this need, I could write Function()
as:
FunctionModifiable( const char* pszFile, int i );
Then make a macro thusly:
#define Function( i ) FunctionModifiable( __FILE__, (i) )
And FunctionModifiable()
would have the duty to check pszFile
in say an unordered_set<>
that was populated during initialization to see if special functionality need be activated.
However, the overhead of that search is a minus (this is high-performance software and the function is called a huge number of times), and there is some per-file data that would need to be cached in this situation. We can eliminate the search, and have get storage for the cached info, by passing in not __FILE__
but a pointer to a helper object. This object needs the filename so that, when it undergoes one-off initialization, it can consult config or environment variables or what have you to know whether it needs special handling.
FunctionHelperObject fho( __FILE__ );
#define Function( i ) FunctionModifiable( &fho, (i) ) // C-style solution
#define Function( i ) fho.MethodModifiable( (i) ) // C++-style solution
OK, now say I want to avoid users having to define that fho
in every file. (Inter alia, we can't re-write all existing files calling Function(), though say we're willing to recompile them).
The idea I had was the unusual step of putting a variable definition in the header file, so that any program including the header for Function()
would get a FunctionHelperObject fho( __FILE__ )
for free. (Such definition would be #pragma once
or guarded by a preprocessor variable.
The problem is that __FILE__
at that point would be the name of the header, not of the top-level compilation unit. If there was a __CFILE__
symbol, that would be the solution, but there's not.
Ultimately the best I can think of has shortcomings: 1) the "modifiable" aspect would only be available in source code explicitly written to use it, and 2) you'd have to do that explicit writing, and 3) starting to get a little complicated. In code you want to add the ability to modify behavior to you'd write USE_MODIFIABLE_FUNCTION
somewhere after including the header in question. That'd be a macro that creates the FunctionHelperObject
above, this time in the right "file" so __FILE__
would have the required value, and furthermore defines a macro as seen above that would mask the non-customizable function Function()
with one of the two macros seen above. In short: the previous example, plus
#define USE_MODIFIABLE_FUNCTION FunctionHelperObject fho( __FILE__ );\n#define Function( i ) fho.MethodModifiable( (i) )
Code written without USE_MODIFIABLE_FUNCTION
would simply call the uncustomizable Function()
the normal way.
But surely this is some other accepted, portable way to provide this behavior? Although I've talked exclusively about the C preprocessor, is there perhaps any C++ template magic or any other approach that would work?