I have logging function being called at several places throughout the code. To every log, I have to supply 2 compile time constants. There are 2 approaches to accomplish:
(1) Function argument:
template<typename T>
void log (const T &obj, const int LINE, const int COUNT)
{
// T is used for some purpose
if(debug)
logging(obj.out(), LINE, COUNT);
}
call it as,
log(str, __LINE__, __COUNTER__);
(2) Template parameter:
template<typename T, int LINE, int COUNT>
void log (T &obj)
{
// T is used for some purpose
if(debug)
logging(obj.out(), LINE, COUNT);
}
call it as,
log<__LINE__, __COUNTER__>(str);
I am not able to decide, because 1st approach offers simplicity, but we are passing constant at compile time. 2nd approach is perfect, but compilation time would probably increase. This task is tedious, and I haven't implemented any of them yet, so I don't have any bench mark.
It will be a great help if someone can answer this from their experience/knowledge.
"A function template is a template that is used to generate functions. A template function is a function that is produced by a template. For example, swap(T&, T&) is a function tem-plate, but the call swap(m, n) generates the actual template function that is invoked by the call."
In computing, compile-time function execution (or compile time function evaluation, or general constant expressions) is the ability of a compiler, that would normally compile a function to machine code and execute it at run time, to execute the function at compile time.
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
Which one is suitable syntax for function template? Explanation: Both class and typename keywords can be used alternatively for specifying a generic type in a template.
Since the choice between these two makes a difference to the calling code, I would recommend logging via a macro. Then you don't have to worry now about which of these is better, because it's easy to switch between them.
Once you have your real application written, you can mess with the macro definition to compare the two. Or not, if there are more productive areas to optimize. If it turns out to make a big difference, you can even leave it open to the build config to decide whether to use -DLOGGING_COMPILES_QUICKLY
or -DLOGGING_RUNS_QUICKLY
.
Another potential benefit of a macro: you could arrange that the first argument is evaluated if and only if debug
is true. I don't know what the interface of str
is, or where those objects come from, but if it costs anything to produce the right value to pass to log
, and then log
doesn't use it in the non-debug case, then that's a potential waste of runtime.
I would go with the first option. The performance impact of passing two integers is negligible. The optimizer will also probably inline the function call in which case there would be no difference between the two. The second option I think is a bad idea, since you will be creating a lot of versions of the same function, for no reason.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With