[C++] Passing functions as template arguments
Function pointers allow us to inject functionality into other functions. A common use case is passing comparison functions into a sorting function.
One issue with function pointers is the compiler cannot optimise the function call as it isn’t known until runtime. There is also a slight performance overhead from having to load the function’s address into a register before it can be called.
If we know what function we want to call at compile time, these issues can be solved by passing the pointer as a template argument. The compiler then has full knowledge of the call and can apply the usual optimisations to it.
Here is a trivial example.
template <auto fn>
auto call_fn(auto value) {
return fn(value);
}
int main() {
volatile auto x{call_fn<[](auto x) { return x + 1;}>(1)};
return 0;
}
The asm output shows the call is completely optimised out and the result is used directly.
value$ = 8
auto call_fn<`int main(void)'::`2'::<lambda_1_>{},int>(int) PROC ; call_fn<`main'::`2'::<lambda_1_>{},int>, COMDAT
lea eax, DWORD PTR [rcx+1]
ret 0
auto call_fn<`int main(void)'::`2'::<lambda_1_>{},int>(int) ENDP ; call_fn<`main'::`2'::<lambda_1_>{},int>
this$ = 8
x$ = 16
auto `int main(void)'::`2'::<lambda_1_>::operator()<int>(int)const PROC ; `main'::`2'::<lambda_1_>::operator()<int>, COMDAT
lea eax, DWORD PTR [rdx+1]
ret 0
auto `int main(void)'::`2'::<lambda_1_>::operator()<int>(int)const ENDP ; `main'::`2'::<lambda_1_>::operator()<int>
x$ = 8
main PROC ; COMDAT
mov DWORD PTR x$[rsp], 2
xor eax, eax
ret 0
main ENDP