In general C++ does not use call-by-name. Call-by-name means that the argument to the function is not evaluated on function call. It behaves as if the argument would be substituted into the function body.
Example:
void foo(int a, int b) {
int s = 0;
for(int i=0; i<n; i++) {
s += b;
}
}
Normally in C++ an example expression like x = foo(3,bar(7));
would behave similar to this:
int tmp = bar(7);
x = foo(3,tmp);
bar
is evaluated once and the result given to the function foo
.
A language which would use call-by-name would potentially transform foo(3,bar(7));
to
void foo() {
int s = 0;
for(int i=0; i<3; i++) {
s += bar(7);
}
}
In the first case the function bar
would be evaluated once, in the second case it would be evaluated 3
times.
However there are exceptions to that rule. When the function declaration is known (e.g. for templates and inlines) the optimizer may use it to generate optimized code.
Example:
inline unsigned foo(unsigned a, unsigned b) {
return a / b;
}
If you call a = foo(x,2);
the compiler would be smart enough to translate that to a = x/2;
and then to a = x >> 1;
.
This even goes as far as this example:
inline int foo(int a, int b) {
if(a == 0) return 0;
else return b;
}
Now the compiler can indeed transform x = foo(0,bar(17));
to x = 0;
thus never calling the function bar
. I think this optimization is only done when it is assured that bar
has not side-effects.
While C++ does not use call-by-name you can easily use the ideom in C++. Just give a function object/pointer to your function.
Example:
template<typename F>
int foo(int a, F b) {
int s = 0;
for(int i=0; i<a; i++) {
s += b();
}
}
Now with foo(3, []() { static int i=0; return i++; })
, where the second argument is a C++11 lambda, b would be evaluated each time it is encountered in you code.