Consider the following:
#include <iostream>
int main()
{
x = 10;
void x_squared(int x) // Illegal: Nested function detected
{
std::cout << x * x << "\\n";
}
x_squared(); // function call
}
According to the rules of C++, nested functions are illegal. Functions must be implemented in the global namespace. Then they can be called in other functions.
Additionally, if it was legal it opens a can of worms:
- Should
printX()be able to accessx? - If yes, how should that captured state be represented?
- How long should it live?
- What happens if the nested function escapes the scope?
Therefore, in C++ functions can call other functions, but ordinary named functions cannot be defined inside other functions.
Why is this the case?
This behaviour was inherited from C.
The justification was to simplify compilers, abide to memory limitations (back when computers were slow) and speed up runtime organization.
Where functions can be defined
It is not quite correct to say that functions must be implemented in the global namespace.
They can be defined at namespace scope:
#include <iostream>
void printSquare(int value){
std::cout << value * value << '\n';
}
int main(){
int x { 10 };
printSquare(x);
}
They can also be placed inside a named namespace:
#include <iostream>
namespace math
{
void printSquare(int value){
std::cout << value * value << '\n';
}
}
int main(){
math::printSquare(10);
}
Or they can be class member functions:
#include <iostream>
class Printer {
public:
void printSquare(int value) const{
std::cout << value * value << '\n';
}
};
int main(){
Printer printer {};
printer.printSquare(10);
}
So the accurate rule is:
C++ does not allow ordinary named function definitions inside block scope.
A function body creates block scope. You cannot define a normal function there.
The alternative
C++ does have alternatives such as std::function, lambdas and std::bind which perform the same purpose.
Let’s refactor the example at the beginning of the page to use a lambda expression
We use a capture clause to capture x, which is defined in the function scope. This, allows the lambda to use it.
void foo() {
int x = 10;
auto x_squared = [x]() {
std::cout << x * x << "\n";
};
x_squared();
}
Takeaway
C++ does not support ordinary named functions nested inside other functions.
If the helper is generally useful, define it at namespace scope. If it belongs to an object, make it a member function. If it is small and only needed locally, use a lambda