At compile-time, I want to pass a (stateless) function as efficiently as possible. I see two options:
template<typename Functor>
bool PassAsArgument(int arg1, int arg2, Functor functor);
and
template<bool (*Function)(int, int)>
bool PassAsTemplateParameter(int arg1, int arg2);
The second option seemed like the obvious choice for compile-time computation, however, Effective STL #39, the C++ standard library (std::sort
, std::make_heap
), the C++ Core Guidelines (T.40), and this stackoverflow answer disagree. I tested the both versions on godbolt and found that the optimizations I wanted were applied (i.e., std:less<int>
was inlined).
#include <functional>
template<typename Functor>
bool PassAsArgument(int arg1, int arg2, Functor functor){
return functor(arg1, arg2);
}
template bool PassAsArgument(int, int, std::less<int>);
results in
bool PassAsArgument<std::less<int> >(int, int, std::less<int>):
cmp edi, esi
setl al
ret
and
inline bool LessThan(int a, int b){
return a < b;
}
template<bool (*Function)(int, int)>
bool PassAsTemplateParameter(int arg1, int arg2){
return Function(arg1, arg2);
}
template bool PassAsTemplateParameter<LessThan>(int, int);
results in
bool PassAsTemplateParameter<&(LessThan(int, int))>(int, int):
cmp edi, esi
setl al
ret
I want to follow the guidelines, but I'm worried that in more complicated code, I may make a mistake that disables some optimizations. For example,
- What if
Functor
is not the last argument? - What if I call
PassAsArgument
with a statefulFunctor
? - What if I need to pass multiple
Functor
s? - What if I need to pass
Functor
tofunc2
in the body ofPassAsArgument
? - What if I save a copy of
Functor
as a data member of a class?
As a starting point, I need to know what optimizations the compiler is using. The question is: What optimization allows Functors passed-by-value to be inlined?