(From comments beneath question)
Note the subtlety: the point of declaration of rev
is, syntactically, exactly at the occurrence of the declarator rev
:
// vvv Point of declaration
std::function<void(char* b, char* e)> rev =
[&](char* b, char* e) { if (1<e-b) { std::swap(*b,*--e); rev(++b,e); }
After that (including the equals sign and everything that follows), rev
now represents a valid object with a known type (and size), and it can be used like any other defined variable in scope.
Also, think about how the compiler builds this code:
When it compiles the call to rev
(inside the function definition), this is:
- simply building a stack frame (with known parameters being passed), and
- calling a jmp (to a known address)
... The actual function being called is irrelevant, as long as its signature and location is known (and the latter information is available to the compiler at the point of declaration).
The rest of the function is, of course, straightforward for the compiler to build, as well.
So, despite the seeming strangeness of 'defining a function in terms of itself', it works straightforwardly.