>> Yes they can in fact. So the object can outlive the scope. > > As I understand the lambda proposal, the lambda function may not refer > to things that have gone out of scope. It can use *references* that > have gone out of scope, but only if the referent is still in scope. > Since the way that something like: > > int i; > void f() { > int &a = i; > ...<>() { return a; } ... > } > > should be implemented is with a lambda-local copy of "a" (rather than a > pointer to "a"), this is OK.
This is valid but has the following behaviour: int i; tr1::function<int()> f() { int & a = i; return <>() -> int {return a;}; } void doit() { i = 1; tr1::function<int()> g(f()); assert(g()==1); i = 2; // Change the global variable assert(g()==1); // f() returned an object that has a copy of a } According to my reading of n1968, this is valid code that does not invoke undefined behaviour. That is, the unnamed function has a copy of the stack (only the relevant variables though) by default. So it is valid to use stack variables in the newly created function. To reproduce the case you suggest above, the definition of f() would be (something like): tr1::function<int()> f() { // explicitly keep a reference to i , keeping a reference to a local // variable is UB and could be a diagnostic return <> -> int extern (i){ return i; }; } > So, I do think that nested functions would be a natural implementation > in GCC, since they already provide access to a containing function's > stack frame. I think the compiler could be smart in certain cases and reduce a n1968 function to a nested function. This is the case when all variables referenced in the anonymous function are listed in the extern(...) block or in the parameter list *and* the new function is not returned to callers. I don't think this can be done in general though. Even for n1958 functions, there is a way to keep a copy of the stack (and then return this new function, with copies intact). Currently, I am looking at the n1968 proposal. You referenced the n1958 proposal. I don't know which one will eventually be accepted and don't particularly care either way, I just want to learn gcc ;) In either case though, we have to handle the case where the new object has copies of the data on the stack/global scope. > You could also use the anonymous-class approach that you > suggested, but, as the lambda proposal mentions, using a nested function > may result in better code. I suspect that what you want is a class (to > meet the requirements on ret_type, etc.) whose operator() is marked as a > nested function for GCC, in the event -- and *only* in event -- that the > lambda function refers to variables with non-static storage duration. I think this can be an optimization, yes. > Also, it appears to me that there is something missing from N1958: there > is no discussion about what happens when you apply typeid to a lambda > function, or otherwise use it in a context that requires type_info. > (Can you throw it as an exception, for example?) Can you capture its > type with typeof()? Can you declare a function with a paramter of type > pointer-to-lambda-function? Is this discussed, or am I missing something? I think it's typeid is undefined but it has a valid type_info object. Consider a function f(int) that keeps something by value and another by reference with same call signature. Two different types. For most purposes, people would be using tr1::function. The only places it would affect is generic code (i.e., templates). But if generic code uses typeid... That misses the whole point, I think. Otherwise, I think you could capture its type using typeof. Catching it as an exception would be difficult unless you can use typeof. I think a new intermediate tree type would be beneficial. Atleast one pass is necessary after the object is constructed to enable the nested function optimization. Of course, all this is silly if nested functions carry around their lexical scope and can be returned. But I dont know that they do. Thanks for your reply, Sohail