As already stated in the comment, a compiler may be able to optimize such thing if it can detect that the called function is a pure function (no side effects, no i/o, ...).
A small example (https://godbolt.org/g/2b3Vgg) with g++:
#include <cmath> extern double g (double); template <double (*F) (double)> double f1 (double angle) { double x = 3 * F(angle) + F(angle); double y = F(angle) + F(angle) * F(angle); return x + y * F(angle); } template double f1<sin> (double); template double f1<g> (double);
In f1 you have multiple calls to the F function, and two instanciations:
- One with
std::sin - Which should be considered a pure function by any sane compiler. - One with an
extern function which cannot be considered a pure function.
If you look at the generated assembly*:
double f1<&sin>(double): subq $8, %rsp call sin ... ret double f1<&(g(double))>(double): subq $40, %rsp movsd %xmm0, (%rsp) call g(double) movsd %xmm0, 8(%rsp) movsd (%rsp), %xmm0 call g(double) movsd 8(%rsp), %xmm1 mulsd .LC0(%rip), %xmm1 ... call g(double) movsd %xmm0, 16(%rsp) movsd (%rsp), %xmm0 call g(double) movsd %xmm0, 24(%rsp) movsd (%rsp), %xmm0 call g(double) mulsd 24(%rsp), %xmm0 movsd 16(%rsp), %xmm2 ... call g(double) mulsd 16(%rsp), %xmm0 addsd 8(%rsp), %xmm0 ...
You see that in the instantiation with sin, g++ only do one function call (call sin) while in the instantiation with g, you have 6 calls.
So yes, the compiler may do some optimization regarding multiple calls to pure function but I would not rely on it** and use an explicit intermediate variable as in your second example.
* I removed most of the generated instructions but all the call instructions are shown.
** clang does not optimize this even with -O3 (but it does with -ffast-math).
double S= sin(Angle)can save you a lot of typing...