was the idea of nested functions considered to be useless during the time of developing older c++ standard, because its usage is basically covered by another concept like object-oriented programming; or it wasn't implemented just as a matter of simplification?

Recommended Answers

All 8 Replies

c++ was derived from C, and C never ha them either.

What would be the purpose of a nested function? What features could nested functions give you that normal functions do not?

The reason is that it is difficult to implement nested functions in a way that maintains compatibility with C and other compilers. For example:

extern void f(void (*)());

int main()
{
    int x;
    void g() { x = 42; }
    f(g);
}

In order for this program to work, f, which is compiled separately, has to have access to information that allows it to determine the location of the local variable x inside main.

The typical implementation technique for solving this problem is to say that function pointers are two words long: One word contains the address of the function's code; the other contains the address of the most recently instantiated stack frame of the statically enclosing function.

Trouble now ensues if the function f is in a language whose compiler does not know about this convention.

It is possible to sidestep the compatibility problem by saying, essentially, that global functions and netsted functions have pointers that have two different types. Several people on the C++ committee actually sketched out an implementation strategy that would have made it possible to do so. However, after protracted discussion, the committee ultimately decided that the added implementation complexity was not worth the benefit. If I remember correctly, it was a fairly close decision.

commented: that was a lucid explanation. thanks. +6

c++ was derived from C, and C never ha them either.

What would be the purpose of a nested function? What features could nested functions give you that normal functions do not?

I think just by taking a look at definition of a nested function, its features become clear.

I think arkoenigs answers makes a lot of sense, and I trust that he's right.

By opposition to C and C++, look at Pascal and Object Pascal (or Delphi). Delphi has nested functions because it was extended from Pascal that already had those too. It's a matter of linking strategies and other compiler intricacies (like arkoenig mentioned), which are quite different in C++ and Delphi (I know, I started in Delphi, and it took me a while to move from the Smart Linker of Delphi to the so-called Stupid Linker of C++, which is arguably better, or worse, opinions are quite evenly split on that, as far as I know). There are obviously more issues than just "Is it a nice feature? Yes! then we'll add it!" I think none could argue that nested functions are useless, but are they worth the trouble? Especially based on C, it's quite a hassle to add that feature, as arkoenig said.

C is about as close as one can get to assembly without actually writing assembly. Before C could support nested functions there would have to be support for them in assembly language. And I know that its not supported on Intel based computers, and probably not any other processors either.

If pascal supports nested functions then the pascal compiler must be actually making them separate functions like C language because the underlying assembly language stack frames doesn't support that.

I think just by taking a look at definition of a nested function, its features become clear.

There is no such thing as nested functions in C language, so the features are not clear at all.

AFAIK, the main advantage of nested functions in languages that have them is to provide support for closures. http://en.wikipedia.org/wiki/Closure_%28computer_science%29

Closures typically appear in languages that allow functions to be first-class values, in other words, such languages allow functions to be passed as arguments, returned from function calls, bound to variable names, etc., just like simpler types such as strings and integers. - Wiki

C++ already had function objects, which look like functions but are really first class values, they can be stored, mutated, passed as arguments and returned and bound to variable names. And therefore C++ already had a mechanism for supporting closures - several libraries eg. Boost::bind, Boost::spirit, Boost::phoenix do exploit closures extensively.

To define a function object, the programmer has to go outside the current scope, and these names cannot be declared close to their first (and often only) use. Lambda functions have been added in C++0x to increase the expressive power and ease of use of the language - anything that could be done using lambda functions could also be done using function objects, albeit in a more verbose manner.

In C, gcc has had an extension which provides limited support for nested functions and closures for quite some time now. http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html One can only call these functions (with closures) as long as the containing stack frame is alive:

If you try to call the nested function through its address after the containing function has exited, all hell will break loose. - GNU documentation

GCC implements nested functions via a simple trampoline bounce; the nested function does not store any state information about closures, instead they are picked up directly off the stack frame.

Apple has an implementation of closures in C (called blocks) using the Clang/LLVM front end. http://en.wikipedia.org/wiki/Blocks_%28C_language_extension%29 Unlike nested functions in gcc, these are true closures; blocks can be safely called after the containing scope has exited. Needless to say, the containing lexical scope is stored internally as an object with state.
http://clang.llvm.org/doxygen/Scope_8h_source.html
http://clang.llvm.org/docs/BlockLanguageSpec.txt
http://clang.llvm.org/docs/Block-ABI-Apple.txt

IIRC, Apple has submitted their specification for closures in C to the ANSI/ISO C Standards Committee.

AFAIK, the main advantage of nested functions in languages that have them is to provide support for closures. http://en.wikipedia.org/wiki/Closure_%28computer_science%29

Yes.

C++ already had function objects, which look like functions but are really first class values, they can be stored, mutated, passed as arguments and returned and bound to variable names. And therefore C++ already had a mechanism for supporting closures - several libraries eg. Boost::bind, Boost::spirit, Boost::phoenix do exploit closures extensively.

The decision not to implement member functions came long before Boost, or even STL, existed. I think (but do not remember for sure) that function objects did exist, and their existence contributed to the discussion. Essentially, one camp thought that function objects could easily substitute for nested functions; another thought that programmers would have difficulty writing such substitutions and getting them right.

In particular, one difficulty with using function objects as closures is that each time you define a function object, it is a new type. So to use them in any generality, you may find templates creeping in where they're not really needed.

In C, gcc has had an extension which provides limited support for nested functions and closures for quite some time now. http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html One can only call these functions (with closures) as long as the containing stack frame is alive:
GCC implements nested functions via a simple trampoline bounce; the nested function does not store any state information about closures, instead they are picked up directly off the stack frame.

Yes, and that's a clever technique. The restriction on calling a nested function only so long as its containing stack frame is alive is entirely reasonable, because once a stack frame is gone, there is no reason to believe it will ever be possible to recreate it. If nothing else, the objects that it contained will have been destroyed (by executing their destructors).

However, there are two problems with using the gcc technique to implement nested functions in general: (1) If your implementation does not already use that technique, introducing it is apt to break object-code compatibility; (2) I believe it relies on the ability to execute code that is located on the stack, and some operating systems prohibit such execution for security reasons.

Independently of all this, closures become dramatically more useful in the presence of garbage collection.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.