Topic: Nested functions? TC++PL: "Constructs ought to nest ...


Author: llewelly <llewelly.at@xmission.dot.com>
Date: Thu, 27 May 2004 23:59:43 CST
Raw View
ahp6@email.byu.edu ("Adam H. Peterson") writes:

> llewelly wrote:
>> And re-live the hideousness which is mem_fun and mem_fun_ref? No. The
>>     worst mistake of pointers to member functions was to make them
>>     incompatible with pointers to functions. At the time they were
>>     introduced, nobody knew the trouble this would cause with
>>     generics, but now we do, and we should not repeat this error with
>>     nested functions.
>
> I don't understand how you would get around this.  If you only have a
> pointer to a member function, how do you invoke it?

If you only have a pointer to a *non*-member function, how do you
    invoke it?

The answer is the same. You provide the necessary parameters. Your
    mistake is in thinking the object used to invoke the member function
    is not a parameter.

Consider:

    struct foo
    {
      void bar();
    };

    void non_member_bar(foo& f)
    {
        f.bar();
    }

    int main()
    {
      void(*fp)(foo&) = &non_member_bar;

      foo f;
      fp(f);
    }

By wrapping a member function in a non-member function, we can get a
    pointer to function which is equivalent to the pointer-to-member
    function obtaned by &foo::bar, and yet compatible with pointers to
    non-member functions. Why shouldn't the compiler do this for me?

If the simple work-around above scaled to templates and dozens of
    member-functions from third-party libraries that need to be
    passed to STL algorithms as functors, I wouldn't mind, but the
    boost::bind people have put a lot of hard work into making it scale,
    but are not yet 100% successful.

> How could you
> make a member function pointer compatible with a function pointer (if
> you could do it all over again)?



> What would it mean to call a member
> function without calling it on an instance?

You are mistaken to assume I want to call member functions without
    instances. That would be like calling non-member functions
    without parameters.

In the example I give above, it isn't possible to call non_member_bar
    without passing it a foo, but that doesn't make anybody think a
    pointer to non_member_bar is impossible.

>
> <snip>
>
>> nested functions should have a pointer type compatible with
>>     non-nested functions.
>
> I see implementation problems here as well.

I think you are seeiing things backwards. Nested functions need to be
    designed first. Then the implementation problems can be considered.

> How would you implement
> it such that a nested function could be called like a normal function
> without providing a facility to pass it a pointer to its context?

You are assuming that providing a facility to pass a pointer to its
    context needs to make it incompatible with non-nested
    functions. That is not true;

You are also assuming that it is necessary to provide a facility to
    pass a pointer to its context. That isn't necessary either (it is
    may be desireable, but not necessary; gcc's nested functions provide
    no such facility.)

> How
> would such a function access the context when invoked?

It depends on the design of the nested function feature. One way you
    can learn by investigating the design and implementation of gcc's
    nested functions, see http://gcc.gnu.org/readings.html and read
    the pdf linked by 'Lexical Closures for C++'. (but note that since
    2.9x, gcc has only supported nested functions for C).

For different kind of nested function, which can only access static
    local vars, consider this example of conforming ISO C++ (btw, much
    thanks to Gaby for reminding me of this.) :

    int (*foo())()
    {
      static int i= 0;
      struct bar
      {
        static int baz(){return ++i;}
      };

      return &bar::baz;
    }

    int main()
    {
      int (*f)() = foo();
      f();
    }

Here, access to the context is handled by two tricks: (0) only static
    local vars can be accessed, and so (1) ordinary binding for
    static vars can be done at compile time.

Now, since ISO C++ already supports the above, why can't it support this:

    int (*foo())()
    {
      static int i= 0;
      static int baz(){return ++i;}

      return &baz;
    }

    int main()
    {
      int (*f)() = foo();
      f();
    }

    ?

If nested functions are to mean full closures with full support for
    upward funargs (returing pointers to functions and calling them
    outside of the original nested context), more complex technieques
    must be pursued. (I will try to work on a long post to explain one
    this weekend. It will be based on what I know of how closures can be
    implemented in scheme, and depending on how much time I have, it
    may or may not require garbage collection. )
>
> Personally, I believe the imposition of type compatibility between
> nested functions (with access to enclosing scope) and namespace
> functions is a showstopper.

Depending on what a nested function *is*, it may mean anything from no
    extra work at all, to a good deal of extra work; but given that
    other languages, do it, I don't believe it is 'impossible'.


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly <llewelly.at@xmission.dot.com>
Date: Tue, 25 May 2004 15:49:54 CST
Raw View
gdr@cs.tamu.edu (Gabriel Dos Reis) writes:

> llewelly.at@xmission.dot.com (llewelly) writes:
>
> | Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
> |
> | > llewelly.at@xmission.dot.com (llewelly) writes:
> | >
> | > | do-not-spam-benh@bwsint.com (Ben Hutchings) writes:
> | > | [snip]
> | > | > There is a way to avoid this, which is for the implementation to
> | > | > generate wrapper functions dynamically.  This is how GCC supports
> | > | > nested functions without breaking binary compatibility.
> | > | > However, such
> | > | > dynamic code generation is not possible in all environments
> | > | > in which
> | > | > C++ is and should be supported.
> | > | [snip]
> | > |
> | > | Note that g++ does not support nested functions for C++; they are a
> | > |     C-only extention.
> | >
> | > And from what I can read from people that consider themselves as
> | > "C-only" developers and appreciate GNU extensions, that nested function
> | > extension is qualified "one of the worst" mistakes that ever went into
> | > GNU C.
> | > I recall that a coding standard in the GNU/Linux kernel has some
> | > editorial comments about nested functions.
>
> Since this comment, I've received several requests to provide links
> that support it,  I'll take this opportunity to make a public reply
> where I give links to a very recent discussion on the GNU/Linux kernel
> development list.  The whole thread I have in mind started here:
>
>
>    http://seclists.org/lists/linux-kernel/2004/May/2355.html
>
> | I can't find any mention of nested or inner functions in
> |     linux-2.6.3/Documentation/CodingStyle. I couldn't turn up any
>
>     http://seclists.org/lists/linux-kernel/2004/May/2397.html
>
> |     discussions about their goodness/badness with some googling,
> |     either. The Hurd hacking guide mentions only that they are used
> |     frequently.
>
>
>    http://seclists.org/lists/linux-kernel/2004/May/2361.html
>    http://seclists.org/lists/linux-kernel/2004/May/2362.html
>    http://seclists.org/lists/linux-kernel/2004/May/2365.html
>    http://seclists.org/lists/linux-kernel/2004/May/2392.html
>    http://seclists.org/lists/linux-kernel/2004/May/2397.html

Thank you for these links. However, lots of vitriol, but AFICS, no
    good explaination of *why* GCC nested functions are 'bad'; there
    is a brief mention of problems with upward funargs (namely, as I
    already mentioned, no nested function which uses local vars of
    outer functions can be safely called outside of those functions),
    which seems easy to stumble over, but is it really any worse than
    the ability to return references or pointers to local variables?
    Maybe, I don't know, but we are exactly where we were before.






---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: brangdon@cix.co.uk (Dave Harris)
Date: Wed, 26 May 2004 02:03:07 +0000 (UTC)
Raw View
ahp6@email.byu.edu (Adam H. Peterson) wrote (abridged):
> Local functions that are going to have access to the enclosing scope, I
> believe, will need to have fat pointers associated with them, to
> include reference information to the enclosing scope.  In light of
> this, perhaps such pointers should either be disallowed or be given a
> different type reminiscent of member function pointers.  (Yes, there
> would be semantic differences.)

In my view local functions with access to the enclosing scope should be
full objects with unique types. In simple cases, for example passing to a
template, the overhead could be optimised away. In more complex cases we'd
need an explicit base class and virtual functions.

    struct Callback {
        virtual void operator()( int x ) = 0;
    };

    void use_it( Callback * );

    void demo() {
        int a = 0;
        void my_callback( int x ) : Callback { a += x; }
        use_it( &my_callback );
    }

where demo becomes something like:

    void demo() {
        int a = 0;

        struct __my_callback : Callback {
            int &a;
            __my_callback( int &a ) : a(a) {}
            void operator()( int x ) { a += x; }
        } my_callback(a);

        use_it( &my_callback );
    }

This isn't quite a fat pointer, in that sizeof(&my_callback) is the same
as for any struct pointer. The my_callback object does have a both a
reference and a vtable pointer, but in common situations the reference can
be optimised away.

I think it's more important that local functions be compatible with
ordinary class instances than they be compatible with ordinary function
pointers. Access to local variables is a way of giving the function its
own mutable state, which pretty much makes it a full object, so that's
what it should be in the type system. In practice I would expect cases
like my_callback to mix with complex cases where an explicit non-local
class is needed.

-- Dave Harris, Nottingham, UK

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Wed, 26 May 2004 02:06:29 +0000 (UTC)
Raw View
llewelly wrote:
> And re-live the hideousness which is mem_fun and mem_fun_ref? No. The
>     worst mistake of pointers to member functions was to make them
>     incompatible with pointers to functions. At the time they were
>     introduced, nobody knew the trouble this would cause with
>     generics, but now we do, and we should not repeat this error with
>     nested functions.

I don't understand how you would get around this.  If you only have a
pointer to a member function, how do you invoke it?  How could you make
a member function pointer compatible with a function pointer (if you
could do it all over again)?  What would it mean to call a member
function without calling it on an instance?

<snip>

> nested functions should have a pointer type compatible with
>     non-nested functions.

I see implementation problems here as well.  How would you implement it
such that a nested function could be called like a normal function
without providing a facility to pass it a pointer to its context?  How
would such a function access the context when invoked?

Personally, I believe the imposition of type compatibility between
nested functions (with access to enclosing scope) and namespace
functions is a showstopper.  (I don't see a problem with nested
functions that don't have access, though.  But I don't see everything :) .)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Tue, 25 May 2004 23:54:47 CST
Raw View
On Tue, 25 May 2004, Al Grant wrote:

| news0@nospam.demon.co.uk (John G Harris) wrote in message news:<6b3RysBVKlrAFw1O@jgharris.demon.co.uk>...
| > 1 Would you accept that you can't have pointers to inner functions?
| >
| > 2 No? Then would you accept that inner functions can't access outer
| > variables?
| >
| > 3 No? Then would you accept that inner functions can access only static
| > variables?
| >
| > 4 No? Then would you accept the job of writing the full and precise
| > definition of when destructors are run and when they aren't?
| >
| > I think you were suggesting 2, but others go further.
|
| BCPL had 3.

As does C++ -- for member functions of local classes.

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Wed, 26 May 2004 18:01:07 +0000 (UTC)
Raw View
rlankine@hotmail.com ("Risto Lankinen") writes:

> "llewelly" <llewelly.at@xmission.dot.com> wrote in message
> news:863c5qzmee.fsf@Zorthluthik.local.bar...
>>
>> I will grant the feature seems readily misusable; you can pass the
>>     address of a nested function outside of its outer function, but
>>     you can't safely call the nested function (directly or not) from
>>     outside its outer function.
>
> This is in no way different from passing (or returning) the address
> of (or reference to) a local stack variable.  A local entity is a local
> entity is a local entity...

I don't think it is either; local automatic vars are, as you say,
    'readily misuable' in the same sense, and novice questions on
    comp.lang.c++[.moderated] about problems caused by such misuse
    are as faithful as cron, but one quickly learns what one can
    safely do with the address of a local automatic var. Maybe gcc
    style nested functions would be no different, but maybe there are
    worse problems we haven't seen. That's what I'm trying to find out.



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Thu, 27 May 2004 03:23:24 +0000 (UTC)
Raw View
gdr@cs.tamu.edu (Gabriel Dos Reis) writes:

> dickie@acm.org (Garth A. Dickie) writes:
[snip]
> | This makes me think of returning references or pointers
> | to local variables, which has never been allowed.
>
> It is permitted to return a reference or pointer to an automatic local
> variables, the rest depends on what you do with them.
>
> | Why
> | should we change the rules so drastically just because
> | we want local functions?
>
> Well, I don't want local functions, but I have to listen to other
> people :-)
>
> | Suppose instead that a local function is treated as a
> | local variable. It has access to the automatic variables
> | which were in scope at its declaration, and *the function
> | has a lifetime just like any other object*. Once the
> | function goes out of scope, its lifetime is ended and
> | it cannot be called.  The function is destroyed in the
> | same order as any other variable in its position would be.
>
> So far I think I agree -- it roughly correponds to my mental model of
> lambdas as I would see them in C++.
>
> | In particular, the function is destroyed before the
> | outer-scope variables it references, because it was
> | created after they were created:
> |
> | {
> |     int a = 0;
> |     void foo() { ++a; } // cannot see b
> |     int b = 0;
> |     void bar() { b += a; }
> |
> |     // destruction order is bar, b, foo, a.
> | }
> |
> | This supports the callback or filter use of local functions,
> | but doesn't allow function "factories".
>
> Troubles begins when you take the address of such beast.
[snip]

With gcc's nested functions, it is permitted to return a reference or
    a pointer to a nested function, the rest depends on what you do
    with it. :-)

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Thu, 20 May 2004 03:28:12 +0000 (UTC)
Raw View
Prateek R Karandikar wrote:
> What is the strong reason for functions not nesting? If someone in
> effect wants to create nested functions, it can be done by defining a
> local class with a function defined inside the class definition.

Traditionally, languages which permit nested functions also permit those
functions to access the local variables of the enclosing function, while
local classes do not. So your techniques are inequivalent.

Supporting nested functions with local variable access is complicated
because of pointers to nested functions, which must somehow refer to
the variables of the correct scope(s) when invoked. Various techniques
can be employed for this, but C never had such things, and so neither
did C++.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: do-not-spam-benh@bwsint.com (Ben Hutchings)
Date: Fri, 21 May 2004 04:58:12 +0000 (UTC)
Raw View
Prateek R Karandikar wrote:
> The C++ Programming Language, Third Edition (C.10.2): "Constructs
> ought to nest unless there is a strong reason for them not to."
>
> What is the strong reason for functions not nesting? If someone in
> effect wants to create nested functions, it can be done by defining a
> local class with a function defined inside the class definition.
> Instead of forcing programmers to use this roundabout technique if
> nested functions are ever required, why aren't nested functions
> supported directly?
<snip>

In most languages that support nested functions, a nested function has
access to the local variables of the enclosing function invokation
that made reference to it (and so on up through any further enclosing
functions).  Supposing that C++ supported this, one could write
something like:

    int f(int (* pf)()) { return pf() - 1; }

    int main()
    {
        int i = 5;
        int nf() { return i++; }
        assert(f(nf) == 4 && i == 6);
    }

and the assertion would be true.

This requires that a pointer to a nested function holds not only the
address of the code of the nested function but also the automatic
storage for the enclosing function invokation(s).  Extending function
pointers in this way would require implementors to break binary
compatibility with most C ABIs, which for most users of C++ would not
be an acceptable price.

There is a way to avoid this, which is for the implementation to
generate wrapper functions dynamically.  This is how GCC supports
nested functions without breaking binary compatibility.  However, such
dynamic code generation is not possible in all environments in which
C++ is and should be supported.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Fri, 21 May 2004 05:14:30 +0000 (UTC)
Raw View
Hyman Rosen wrote:

> Prateek R Karandikar wrote:
>
>> What is the strong reason for functions not nesting? If someone in
>> effect wants to create nested functions, it can be done by defining a
>> local class with a function defined inside the class definition.
>
>
> Traditionally, languages which permit nested functions also permit those
> functions to access the local variables of the enclosing function, while
> local classes do not. So your techniques are inequivalent.
>
> Supporting nested functions with local variable access is complicated
> because of pointers to nested functions, which must somehow refer to
> the variables of the correct scope(s) when invoked. Various techniques
> can be employed for this, but C never had such things, and so neither
> did C++.

It's very odd that every time someone asks why C++ doesn't
support nested functions, the answers are mostly along the
lines of "Well, supporting nested functions _with access to
local variables from the surrounding scope_ has implementation
issues, and cost, so it's not done."

It's odd because I suspect that many of the people asking have
no interest in this complication.  They don't want new
capabilities apart from being able to define functions in
a smaller scope.  We make most things as local as possible,
but non-member functions right now must be defined at
namespace scope -- something of an anomaly.

Callback functions are a prime example of functions that
would sometimes be tidier tucked away inside the function
that registers them.

Personally I've grown to accept the C/C++ limitation that
functions definitions cannot be nested, but the most common
reason why the idea is dismissed seems suspect to me.

-- James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Fri, 21 May 2004 06:26:41 +0000 (UTC)
Raw View
do-not-spam-benh@bwsint.com (Ben Hutchings) writes:
[snip]
> There is a way to avoid this, which is for the implementation to
> generate wrapper functions dynamically.  This is how GCC supports
> nested functions without breaking binary compatibility.  However, such
> dynamic code generation is not possible in all environments in which
> C++ is and should be supported.
[snip]

Note that g++ does not support nested functions for C++; they are a
    C-only extention.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Fri, 21 May 2004 16:35:32 +0000 (UTC)
Raw View
James Dennett wrote:
> [...]
> It's very odd that every time someone asks why C++ doesn't
> support nested functions, the answers are mostly along the
> lines of "Well, supporting nested functions _with access to
> local variables from the surrounding scope_ has implementation
> issues, and cost, so it's not done."
>
> It's odd because I suspect that many of the people asking have
> no interest in this complication.  They don't want new
> capabilities  [...]

These are not new capabilities.  Functions defined in a namespace scope
have access to namespace variables.  Function defined in a class scope
have access to class variables (non-static functions to instance and
static data members, and statin functions to static data members).  So why
should functions defined at a function (or deeper) scope be any different?

Victor

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: news0@nospam.demon.co.uk (John G Harris)
Date: Fri, 21 May 2004 20:26:09 +0000 (UTC)
Raw View
In message <kcgrc.598$_o.238@fed1read05>, James Dennett
<jdennett@acm.org> writes

   <snip>
>It's very odd that every time someone asks why C++ doesn't
>support nested functions, the answers are mostly along the
>lines of "Well, supporting nested functions _with access to
>local variables from the surrounding scope_ has implementation
>issues, and cost, so it's not done."
>
>It's odd because I suspect that many of the people asking have
>no interest in this complication.  They don't want new
>capabilities apart from being able to define functions in
>a smaller scope.  We make most things as local as possible,
>but non-member functions right now must be defined at
>namespace scope -- something of an anomaly.
>
>Callback functions are a prime example of functions that
>would sometimes be tidier tucked away inside the function
>that registers them.
   <snip>

1 Would you accept that you can't have pointers to inner functions?

2 No? Then would you accept that inner functions can't access outer
variables?

3 No? Then would you accept that inner functions can access only static
variables?

4 No? Then would you accept the job of writing the full and precise
definition of when destructors are run and when they aren't?

I think you were suggesting 2, but others go further.

   John
--
John Harris

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Sat, 22 May 2004 19:39:53 +0000 (UTC)
Raw View
> These are not new capabilities.  Functions defined in a namespace scope
> have access to namespace variables.  Function defined in a class scope
> have access to class variables (non-static functions to instance and
> static data members, and statin functions to static data members).  So
> why should functions defined at a function (or deeper) scope be any
> different?

On the other hand, classes declared at function scope don't have access
to function variables.  Consider:

void f() {
     int i=0;
     struct C {
         static void g() {
             i=1; // Error
         }
     };
     C::g();
}

int main() {
     f();
}

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dave@whipp.name (Dave Whipp)
Date: Sun, 23 May 2004 00:15:50 +0000 (UTC)
Raw View
v.Abazarov@comAcast.net (Victor Bazarov) wrote:

> These are not new capabilities.  Functions defined in a namespace scope
> have access to namespace variables.  Function defined in a class scope
> have access to class variables (non-static functions to instance and
> static data members, and static functions to static data members).  So why
> should functions defined at a function (or deeper) scope be any different?

As you point out, static functions in class can't access (non-static)
member variables, so there is precident for providing only partial
visibility to variables in the defining scope.

Another perspective is that providing the ability to access local
variables does not need to be as complex as people like to make it.
C++ doesn't prevent you from storing away a pointer to a local
variable (and then returning); so why should protect me against
stashing away a pointer to a function that accesses local variables?
Also, a pointer to a non-static local function is unlikely to be a
regular function pointer, because it would need something analagous to
a "this" pointer as an implicit argument (it couldn't actually be
"this" because "this" is, itself, a local variable).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sun, 23 May 2004 02:05:56 +0000 (UTC)
Raw View
jdennett@acm.org (James Dennett) writes:

[...]

| It's very odd that every time someone asks why C++ doesn't
| support nested functions, the answers are mostly along the
| lines of "Well, supporting nested functions _with access to
| local variables from the surrounding scope_ has implementation
| issues, and cost, so it's not done."

yes, I can see how one can construct arguments against that answer,
but I see nothing particularly wrong with it.

| It's odd because I suspect that many of the people asking have
| no interest in this complication.  They don't want new
| capabilities apart from being able to define functions in
| a smaller scope.

Then, they can just use local classes.

I make the conjecture that, once you allow people to lexically nest
functions inside functions, sooner or latter, they will want to access
automatic variables from surrounding environments -- with the argument
that it is virtually useless to nest functions if you can't access
variables in surrouding neighbors.

|  We make most things as local as possible,
| but non-member functions right now must be defined at
| namespace scope -- something of an anomaly.

No more of anomaly than not being able to nest namespaces at class or
local scope.

| Callback functions are a prime example of functions that
| would sometimes be tidier tucked away inside the function
| that registers them.

I would put them either inside local classes or just in front of the
registering function and have them with internal linkage.

| Personally I've grown to accept the C/C++ limitation that
| functions definitions cannot be nested, but the most common
| reason why the idea is dismissed seems suspect to me.

If it were matematics, I would be seeking for the most beautiful,
effective demonstration... :-)

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: hyrosen@mail.com (Hyman Rosen)
Date: Sun, 23 May 2004 02:06:06 +0000 (UTC)
Raw View
Dave Whipp wrote:
> C++ doesn't prevent you from storing away a pointer to a local
> variable (and then returning); so why should protect me against
> stashing away a pointer to a function that accesses local variables?

The problem isn't in protecting you, it's in making sure that such
a saved pointer to function acesses the right local variables.
Consider the following program. Each saved pointer to f accesses a
different j.

void (*af[10])();

void outer(int i)
{
     int j = 0;
     void f() { ++j; }
     af[i] = &f;
     if (i < 9)
         outer(i + 1);
     for (int k = 0; k <= i; ++k)
         af[k]();
     cout << j << "\n";
}

int main() { outer(0); }

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Sun, 23 May 2004 06:42:39 +0000 (UTC)
Raw View
Victor Bazarov wrote:
> James Dennett wrote:
>
>> [...]
>> It's very odd that every time someone asks why C++ doesn't
>> support nested functions, the answers are mostly along the
>> lines of "Well, supporting nested functions _with access to
>> local variables from the surrounding scope_ has implementation
>> issues, and cost, so it's not done."
>>
>> It's odd because I suspect that many of the people asking have
>> no interest in this complication.  They don't want new
>> capabilities  [...]
>
>
> These are not new capabilities.

I claim that they are.  They don't exist in the language today.

> Functions defined in a namespace scope
> have access to namespace variables.

Yes.

> Function defined in a class scope
> have access to class variables (non-static functions to instance and
> static data members, and statin functions to static data members).

Yes.

> So
> why should functions defined at a function (or deeper) scope be any
> different?

Because local variable are different -- the nested function
would need some kind of pointer back to the stack frame of
its parent function, and *if* we allow the address of the
nested function to be taken then the situation is complicated;
to call the function via that pointer, we must somehow be able
to track down its context (meaning roughly the stack frame of
the function that took its address).

Of course there are various approaches: we could ban taking
the address of a nested function, but that rules out many
likely uses.  We could rule out passing the address of a
nested function to another function for later use.  But if
we just say that nested functions have no special access to
local variables in their containing function, there's no
need to worry about this -- the nested function behaves just
as a namespace-scope function *except* for being more tightly
scoped.

-- James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Sun, 23 May 2004 06:42:47 +0000 (UTC)
Raw View
John G Harris wrote:

> In message <kcgrc.598$_o.238@fed1read05>, James Dennett
> <jdennett@acm.org> writes
>
>   <snip>
>
>> It's very odd that every time someone asks why C++ doesn't
>> support nested functions, the answers are mostly along the
>> lines of "Well, supporting nested functions _with access to
>> local variables from the surrounding scope_ has implementation
>> issues, and cost, so it's not done."
>>
>> It's odd because I suspect that many of the people asking have
>> no interest in this complication.  They don't want new
>> capabilities apart from being able to define functions in
>> a smaller scope.  We make most things as local as possible,
>> but non-member functions right now must be defined at
>> namespace scope -- something of an anomaly.
>>
>> Callback functions are a prime example of functions that
>> would sometimes be tidier tucked away inside the function
>> that registers them.
>
>   <snip>
>
> 1 Would you accept that you can't have pointers to inner functions?
>
> 2 No? Then would you accept that inner functions can't access outer
> variables?
>
> 3 No? Then would you accept that inner functions can access only static
> variables?
>
> 4 No? Then would you accept the job of writing the full and precise
> definition of when destructors are run and when they aren't?
>
> I think you were suggesting 2, but others go further.
>
>   John

Thank you for stating some of the issue clearly.

2 was where I was aiming.  I find the idea of pointers to
nested functions appealing.  3 is reasonable too, and
probably no harder to implement.

Some would have nested functions as full closers, and hence
require garbage collection, but the language they want is
not C++.  And that's fine.  There's room on this planet (and
in many large projects) for more than one programming language.

-- James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Sun, 23 May 2004 07:13:18 +0000 (UTC)
Raw View
jdennett@acm.org (James Dennett) writes:

> Hyman Rosen wrote:
>
>> Prateek R Karandikar wrote:
>>
>>> What is the strong reason for functions not nesting? If someone in
>>> effect wants to create nested functions, it can be done by defining a
>>> local class with a function defined inside the class definition.
>> Traditionally, languages which permit nested functions also permit
>> those
>> functions to access the local variables of the enclosing function, while
>> local classes do not. So your techniques are inequivalent.
>> Supporting nested functions with local variable access is
>> complicated
>> because of pointers to nested functions, which must somehow refer to
>> the variables of the correct scope(s) when invoked. Various techniques
>> can be employed for this, but C never had such things, and so neither
>> did C++.
>
> It's very odd that every time someone asks why C++ doesn't
> support nested functions, the answers are mostly along the
> lines of "Well, supporting nested functions _with access to
> local variables from the surrounding scope_ has implementation
> issues, and cost, so it's not done."
>
> It's odd because I suspect that many of the people asking have
> no interest in this complication.  They don't want new
> capabilities apart from being able to define functions in
> a smaller scope.  We make most things as local as possible,
> but non-member functions right now must be defined at
> namespace scope -- something of an anomaly.

You could define them at namespace scope in one translation unit, and
    then declare them at function scope in the (different)
    translation unit where they were used. This constrains the
    visibility to a smaller scope, but nobody does it.


> Callback functions are a prime example of functions that
> would sometimes be tidier tucked away inside the function
> that registers them.
>
> Personally I've grown to accept the C/C++ limitation that
> functions definitions cannot be nested, but the most common
> reason why the idea is dismissed seems suspect to me.

Different people mean different things by 'nested function'. Some
    people mean full-blown closures. Most people at least expect
    access to local variables of the outer function, but clearly you
    don't consider that necessary.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Sun, 23 May 2004 07:40:31 +0000 (UTC)
Raw View
ahp6@email.byu.edu ("Adam H. Peterson") writes:

| > These are not new capabilities.  Functions defined in a namespace
| > scope have access to namespace variables.  Function defined in a
| > class scope have access to class variables (non-static functions to
| > instance and static data members, and statin functions to static
| > data members).  So why should functions defined at a function (or
| > deeper) scope be any different?
|
| On the other hand, classes declared at function scope don't have
| access to function variables.  Consider:

Unless those variables are static.  For automatic variables, I just
tend to lambda-lift them as constructor parameters.

| void f() {
|      int i=0;
|      struct C {
|          static void g() {
|              i=1; // Error
|          }
|      };
|      C::g();
| }

    void f() {
       int i = 0;

       struct C {
          int& i;
          C(int& v) : i(v) { }
          void g() { i = 1; }
       };

       C(i)::g();
    }

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Gabriel Dos Reis <gdr@cs.tamu.edu>
Date: Sun, 23 May 2004 13:19:54 CST
Raw View
llewelly.at@xmission.dot.com (llewelly) writes:

| do-not-spam-benh@bwsint.com (Ben Hutchings) writes:
| [snip]
| > There is a way to avoid this, which is for the implementation to
| > generate wrapper functions dynamically.  This is how GCC supports
| > nested functions without breaking binary compatibility.  However, such
| > dynamic code generation is not possible in all environments in which
| > C++ is and should be supported.
| [snip]
|
| Note that g++ does not support nested functions for C++; they are a
|     C-only extention.

And from what I can read from people that consider themselves as
"C-only" developers and appreciate GNU extensions, that nested function
extension is qualified "one of the worst" mistakes that ever went into
GNU C.
I recall that a coding standard in the GNU/Linux kernel has some
editorial comments about nested functions.

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: jdennett@acm.org (James Dennett)
Date: Sun, 23 May 2004 20:17:18 +0000 (UTC)
Raw View
llewelly wrote:

> jdennett@acm.org (James Dennett) writes:
>
>
>>Hyman Rosen wrote:
>>
>>
>>>Prateek R Karandikar wrote:
>>>
>>>
>>>>What is the strong reason for functions not nesting? If someone in
>>>>effect wants to create nested functions, it can be done by defining a
>>>>local class with a function defined inside the class definition.
>>>
>>>Traditionally, languages which permit nested functions also permit
>>>those
>>>functions to access the local variables of the enclosing function, while
>>>local classes do not. So your techniques are inequivalent.
>>>Supporting nested functions with local variable access is
>>>complicated
>>>because of pointers to nested functions, which must somehow refer to
>>>the variables of the correct scope(s) when invoked. Various techniques
>>>can be employed for this, but C never had such things, and so neither
>>>did C++.
>>
>>It's very odd that every time someone asks why C++ doesn't
>>support nested functions, the answers are mostly along the
>>lines of "Well, supporting nested functions _with access to
>>local variables from the surrounding scope_ has implementation
>>issues, and cost, so it's not done."
>>
>>It's odd because I suspect that many of the people asking have
>>no interest in this complication.  They don't want new
>>capabilities apart from being able to define functions in
>>a smaller scope.  We make most things as local as possible,
>>but non-member functions right now must be defined at
>>namespace scope -- something of an anomaly.
>
>
> You could define them at namespace scope in one translation unit, and
>     then declare them at function scope in the (different)
>     translation unit where they were used. This constrains the
>     visibility to a smaller scope, but nobody does it.

Possibly because
(1) For those with a C background, there is the feeling that
     this removes consistency checking and leads to bugs that
     show up only at runtime,
(2) For C++, it defers error checking to link time, and
(3) It's no way to cleanly define an interface, scattering in
     client code the claim that some function is supported
     elsewhere.

>>Callback functions are a prime example of functions that
>>would sometimes be tidier tucked away inside the function
>>that registers them.
>>
>>Personally I've grown to accept the C/C++ limitation that
>>functions definitions cannot be nested, but the most common
>>reason why the idea is dismissed seems suspect to me.
>
>
> Different people mean different things by 'nested function'. Some
>     people mean full-blown closures. Most people at least expect
>     access to local variables of the outer function, but clearly you
>     don't consider that necessary.

Indeed.  To my mind, the better scoping alone, and the better
consistency it would give, would be a worthwhile improvement.

-- James

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Mon, 24 May 2004 03:16:24 +0000 (UTC)
Raw View
jdennett@acm.org (James Dennett) writes:

> llewelly wrote:
>
>> jdennett@acm.org (James Dennett) writes:
>>
>>>Hyman Rosen wrote:
>>>
>>>
>>>>Prateek R Karandikar wrote:
>>>>
>>>>
>>>>>What is the strong reason for functions not nesting? If someone in
>>>>>effect wants to create nested functions, it can be done by defining a
>>>>>local class with a function defined inside the class definition.
>>>>
>>>>Traditionally, languages which permit nested functions also permit
>>>>those
>>>>functions to access the local variables of the enclosing function, while
>>>>local classes do not. So your techniques are inequivalent.
>>>>Supporting nested functions with local variable access is
>>>>complicated
>>>>because of pointers to nested functions, which must somehow refer to
>>>>the variables of the correct scope(s) when invoked. Various techniques
>>>>can be employed for this, but C never had such things, and so neither
>>>>did C++.
>>>
>>>It's very odd that every time someone asks why C++ doesn't
>>>support nested functions, the answers are mostly along the
>>>lines of "Well, supporting nested functions _with access to
>>>local variables from the surrounding scope_ has implementation
>>>issues, and cost, so it's not done."
>>>
>>>It's odd because I suspect that many of the people asking have
>>>no interest in this complication.  They don't want new
>>>capabilities apart from being able to define functions in
>>>a smaller scope.  We make most things as local as possible,
>>>but non-member functions right now must be defined at
>>>namespace scope -- something of an anomaly.
>> You could define them at namespace scope in one translation unit,
>> and
>>     then declare them at function scope in the (different)
>>     translation unit where they were used. This constrains the
>>     visibility to a smaller scope, but nobody does it.
>
> Possibly because
> (1) For those with a C background, there is the feeling that
>      this removes consistency checking and leads to bugs that
>      show up only at runtime,
[snip]

And in fact, since most (all?) C implementations do not type check
    function calls at link time, this feeling is quite accurate for
    C; the prototype inside the function may become inconsistent with
    the definition.

For C++ it's not a wholly irrelevent concern; extern "C" functions
    are quite important in many (most?) large projects, and are also
    not type checked at link time in most implementations.


> (2) For C++, it defers error checking to link time, and
> (3) It's no way to cleanly define an interface, scattering in
>      client code the claim that some function is supported
>      elsewhere.

But that's exactly what we do with #include! :-) It's only convention
    that ensures the #included declarations and the linked
    definitions come from the same source.

In fact, I forgot a similey on that comment; I didn't expect anyone
    to take it seriously. But it gave me an idea:

namespace foos_nested_functions
{
    void bar(){/* ... */}
    void baz(){/* ... */}
}

void foo()
{
    using namespace foos_nested_functions;
    /* ... */
    bar();
    baz();
    /* ... */
}

int main()
{
    bar(); //error, bar not in scope here.
}

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Mon, 24 May 2004 03:16:50 +0000 (UTC)
Raw View
jdennett@acm.org (James Dennett) writes:

[...]

| Some would have nested functions as full closers, and hence
| require garbage collection,

Nested functions as full closure do not, by themselves, call for
garbage collection.  It is when you start returning functions by value
that you have to keep track of things that escape.

| but the language they want is
| not C++.  And that's fine.  There's room on this planet (and
| in many large projects) for more than one programming language.

Agreed. C++ cannot be better Haskell than Haskell (and the reverse
holds)  Good programmers should not sick just to one language :-)

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Mon, 24 May 2004 15:48:25 +0000 (UTC)
Raw View
Gabriel Dos Reis <gdr@cs.tamu.edu> writes:

> llewelly.at@xmission.dot.com (llewelly) writes:
>
> | do-not-spam-benh@bwsint.com (Ben Hutchings) writes:
> | [snip]
> | > There is a way to avoid this, which is for the implementation to
> | > generate wrapper functions dynamically.  This is how GCC supports
> | > nested functions without breaking binary compatibility.  However, such
> | > dynamic code generation is not possible in all environments in which
> | > C++ is and should be supported.
> | [snip]
> |
> | Note that g++ does not support nested functions for C++; they are a
> |     C-only extention.
>
> And from what I can read from people that consider themselves as
> "C-only" developers and appreciate GNU extensions, that nested function
> extension is qualified "one of the worst" mistakes that ever went into
> GNU C.
> I recall that a coding standard in the GNU/Linux kernel has some
> editorial comments about nested functions.

I can't find any mention of nested or inner functions in
    linux-2.6.3/Documentation/CodingStyle. I couldn't turn up any
    discussions about their goodness/badness with some googling,
    either. The Hurd hacking guide mentions only that they are used
    frequently.

I will grant the feature seems readily misusable; you can pass the
    address of a nested function outside of its outer function, but
    you can't safely call the nested function (directly or not) from
    outside its outer function.

w.r.t to c++, it seems to me anything that affects name lookup rules
    or overloading rules (and it seems any defintion of nested
    functions would do both) should be approached cautiously , and if
    I'm judging Francis correctly, I'm not the only one of that
    opinion.





---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: dickie@acm.org (Garth A. Dickie)
Date: Mon, 24 May 2004 15:48:42 +0000 (UTC)
Raw View
gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message news:<m365amlrul.fsf@merlin.cs.tamu.edu>...
> It is when you start returning functions by value
> that you have to keep track of things that escape.

This makes me think of returning references or pointers
to local variables, which has never been allowed.  Why
should we change the rules so drastically just because
we want local functions?

Suppose instead that a local function is treated as a
local variable. It has access to the automatic variables
which were in scope at its declaration, and *the function
has a lifetime just like any other object*. Once the
function goes out of scope, its lifetime is ended and
it cannot be called.  The function is destroyed in the
same order as any other variable in its position would be.
In particular, the function is destroyed before the
outer-scope variables it references, because it was
created after they were created:

{
    int a = 0;
    void foo() { ++a; } // cannot see b
    int b = 0;
    void bar() { b += a; }

    // destruction order is bar, b, foo, a.
}

This supports the callback or filter use of local functions,
but doesn't allow function "factories".

Furthermore, if we ever arrive at a syntax for defining
functions inline in expressions, then the rules for lifetime
of temporaries apply to those functions too:

int sum(funky_container v) {
    int result = 0;
    v.internal_iterate(void()(funky_iterator& i){result += *i;});
    // function isn't around any more -- it was a temporary

    void (x&)() = void()() { ++result; };
    // function still exists because x holds a reference to it.

    return result;
}

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: ahp6@email.byu.edu ("Adam H. Peterson")
Date: Mon, 24 May 2004 15:48:51 +0000 (UTC)
Raw View
Gabriel Dos Reis wrote:
> ahp6@email.byu.edu ("Adam H. Peterson") writes:
>
> | > These are not new capabilities.  Functions defined in a namespace
> | > scope have access to namespace variables.  Function defined in a
> | > class scope have access to class variables (non-static functions to
> | > instance and static data members, and statin functions to static
> | > data members).  So why should functions defined at a function (or
> | > deeper) scope be any different?
> |
> | On the other hand, classes declared at function scope don't have
> | access to function variables.  Consider:
>
> Unless those variables are static.  For automatic variables, I just
> tend to lambda-lift them as constructor parameters.

Sure.  No big deal.  But I was giving an example of where a nested scope
doesn't have access to the members of the enclosing scope, addressing
the "we probably shouldn't do it without granting access to the scope,
because scope access happens everywhere else" argument.  There _are_
cases of nested scope without access.  In fact, this example involves a
function that has been indirectly nested.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: cbarron3@ix.netcom.com (Carl Barron)
Date: Mon, 24 May 2004 17:01:03 +0000 (UTC)
Raw View
llewelly <llewelly.at@xmission.dot.com> wrote:

> But that's exactly what we do with #include! :-) It's only convention
>     that ensures the #included declarations and the linked
>     definitions come from the same source.
>
> In fact, I forgot a similey on that comment; I didn't expect anyone
>     to take it seriously. But it gave me an idea:
>
> namespace foos_nested_functions
> {
>     void bar(){/* ... */}
>     void baz(){/* ... */}
> }
>
> void foo()
> {
>     using namespace foos_nested_functions;
>     /* ... */
>     bar();
>     baz();
>     /* ... */
> }
>
> int main()
> {
>     bar(); //error, bar not in scope here.
> }
>
   well there are nested functors that provide access to local variables
up the line :

class outer
{
        int a,b;
        class inner;
        friend class inner;
        class inner
        {
                outer &out;
                class most_inner;
                friend class most_inner;
                class most_inner
                {
                        inner & inn;
                        int a;
                public:
                        most_inner(inner &a_,int b_):inn(a_),a(b_){}
                        int operator () () {return 3*a+1;}
                };
        public:
                explicit inner(outer &x):out(x){}
                int operator () () {return
(most_inner(*this,out.a)()+most_inner(*this,out.b)());}
        };
public:
        outer(int a_,int b_):a(a_),b(b_){}
        int operator () (){return inner(*this)();}
};







---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Adam H. Peterson" <ahp6@email.byu.edu>
Date: Mon, 24 May 2004 14:29:41 CST
Raw View
Local functions that are going to have access to the enclosing scope, I
believe, will need to have fat pointers associated with them, to include
reference information to the enclosing scope.  In light of this, perhaps
such pointers should either be disallowed or be given a different type
reminiscent of member function pointers.  (Yes, there would be semantic
differences.)

Also, perhaps nested functions could be declared "static" in which case
they would not have access to the enclosing scope (or only access to
statics or something) and would have a pointer type compatible with
namespace functions.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: llewelly.at@xmission.dot.com (llewelly)
Date: Tue, 25 May 2004 01:45:10 +0000 (UTC)
Raw View
"Adam H. Peterson" <ahp6@email.byu.edu> writes:

> Local functions that are going to have access to the enclosing scope,
> I believe, will need to have fat pointers associated with them, to
> include reference information to the enclosing scope.  In light of
> this, perhaps such pointers should either be disallowed or be given a
> different type reminiscent of member function pointers.  (Yes, there
> would be semantic differences.)

And re-live the hideousness which is mem_fun and mem_fun_ref? No. The
    worst mistake of pointers to member functions was to make them
    incompatible with pointers to functions. At the time they were
    introduced, nobody knew the trouble this would cause with
    generics, but now we do, and we should not repeat this error with
    nested functions.

>
> Also, perhaps nested functions could be declared "static" in which
> case they would not have access to the enclosing scope (or only access
> to statics or something) and would have a pointer type compatible with
> namespace functions.

nested functions should have a pointer type compatible with
    non-nested functions. So should member functions, if we can
    possibly add that to the language at this late date.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Tue, 25 May 2004 05:55:27 +0000 (UTC)
Raw View
dickie@acm.org (Garth A. Dickie) writes:

| gdr@cs.tamu.edu (Gabriel Dos Reis) wrote in message news:<m365amlrul.fsf@merlin.cs.tamu.edu>...
| > It is when you start returning functions by value
| > that you have to keep track of things that escape.
|
| This makes me think of returning references or pointers
| to local variables, which has never been allowed.

It is permitted to return a reference or pointer to an automatic local
variables, the rest depends on what you do with them.

| Why
| should we change the rules so drastically just because
| we want local functions?

Well, I don't want local functions, but I have to listen to other
people :-)

| Suppose instead that a local function is treated as a
| local variable. It has access to the automatic variables
| which were in scope at its declaration, and *the function
| has a lifetime just like any other object*. Once the
| function goes out of scope, its lifetime is ended and
| it cannot be called.  The function is destroyed in the
| same order as any other variable in its position would be.

So far I think I agree -- it roughly correponds to my mental model of
lambdas as I would see them in C++.

| In particular, the function is destroyed before the
| outer-scope variables it references, because it was
| created after they were created:
|
| {
|     int a = 0;
|     void foo() { ++a; } // cannot see b
|     int b = 0;
|     void bar() { b += a; }
|
|     // destruction order is bar, b, foo, a.
| }
|
| This supports the callback or filter use of local functions,
| but doesn't allow function "factories".

Troubles begins when you take the address of such beast.

| Furthermore, if we ever arrive at a syntax for defining
| functions inline in expressions, then the rules for lifetime
| of temporaries apply to those functions too:
|
| int sum(funky_container v) {
|     int result = 0;
|     v.internal_iterate(void()(funky_iterator& i){result += *i;});
|     // function isn't around any more -- it was a temporary
|
|     void (x&)() = void()() { ++result; };
|     // function still exists because x holds a reference to it.

Yeah, I like Perl when I'm programming in Perl, but I'm not sure I'd
like Perl in C++ :-)

--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Tue, 25 May 2004 05:55:29 +0000 (UTC)
Raw View
llewelly.at@xmission.dot.com (llewelly) writes:

| Gabriel Dos Reis <gdr@cs.tamu.edu> writes:
|
| > llewelly.at@xmission.dot.com (llewelly) writes:
| >
| > | do-not-spam-benh@bwsint.com (Ben Hutchings) writes:
| > | [snip]
| > | > There is a way to avoid this, which is for the implementation to
| > | > generate wrapper functions dynamically.  This is how GCC supports
| > | > nested functions without breaking binary compatibility.  However, such
| > | > dynamic code generation is not possible in all environments in which
| > | > C++ is and should be supported.
| > | [snip]
| > |
| > | Note that g++ does not support nested functions for C++; they are a
| > |     C-only extention.
| >
| > And from what I can read from people that consider themselves as
| > "C-only" developers and appreciate GNU extensions, that nested function
| > extension is qualified "one of the worst" mistakes that ever went into
| > GNU C.
| > I recall that a coding standard in the GNU/Linux kernel has some
| > editorial comments about nested functions.

Since this comment, I've received several requests to provide links
that support it,  I'll take this opportunity to make a public reply
where I give links to a very recent discussion on the GNU/Linux kernel
development list.  The whole thread I have in mind started here:


   http://seclists.org/lists/linux-kernel/2004/May/2355.html

| I can't find any mention of nested or inner functions in
|     linux-2.6.3/Documentation/CodingStyle. I couldn't turn up any

    http://seclists.org/lists/linux-kernel/2004/May/2397.html

|     discussions about their goodness/badness with some googling,
|     either. The Hurd hacking guide mentions only that they are used
|     frequently.


   http://seclists.org/lists/linux-kernel/2004/May/2361.html
   http://seclists.org/lists/linux-kernel/2004/May/2362.html
   http://seclists.org/lists/linux-kernel/2004/May/2365.html
   http://seclists.org/lists/linux-kernel/2004/May/2392.html
   http://seclists.org/lists/linux-kernel/2004/May/2397.html


--
                                                        Gabriel Dos Reis
                                                         gdr@cs.tamu.edu
  Texas A&M University -- Computer Science Department
 301, Bright Building -- College Station, TX 77843-3112

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rlankine@hotmail.com ("Risto Lankinen")
Date: Tue, 25 May 2004 16:00:55 +0000 (UTC)
Raw View
"llewelly" <llewelly.at@xmission.dot.com> wrote in message
news:863c5qzmee.fsf@Zorthluthik.local.bar...
>
> I will grant the feature seems readily misusable; you can pass the
>     address of a nested function outside of its outer function, but
>     you can't safely call the nested function (directly or not) from
>     outside its outer function.

This is in no way different from passing (or returning) the address
of (or reference to) a local stack variable.  A local entity is a local
entity is a local entity...

 - Risto -

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: algrant@myrealbox.com (Al Grant)
Date: Tue, 25 May 2004 12:54:55 CST
Raw View
news0@nospam.demon.co.uk (John G Harris) wrote in message news:<6b3RysBVKlrAFw1O@jgharris.demon.co.uk>...
> 1 Would you accept that you can't have pointers to inner functions?
>
> 2 No? Then would you accept that inner functions can't access outer
> variables?
>
> 3 No? Then would you accept that inner functions can access only static
> variables?
>
> 4 No? Then would you accept the job of writing the full and precise
> definition of when destructors are run and when they aren't?
>
> I think you were suggesting 2, but others go further.

BCPL had 3.  Inner functions could access local statics and other
local functions.  Parameters and automatic locals were visible
but it was a compile-time error to use them, something like:
  "inner function refers to dynamic free variable"

Situation 3 was accepted by BCPL programmers and implementers as
being the right compromise between power and implementability in
its class of languages.  C and C++ are in the same class.  If the
feature was dropped from C because it added more complexity than
it was worth to the front-end syntax analysis, surely that does
not apply to C++.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kprateek88@yahoo.com (Prateek R Karandikar)
Date: Wed, 19 May 2004 19:47:58 +0000 (UTC)
Raw View
The C++ Programming Language, Third Edition (C.10.2): "Constructs
ought to nest unless there is a strong reason for them not to."

What is the strong reason for functions not nesting? If someone in
effect wants to create nested functions, it can be done by defining a
local class with a function defined inside the class definition.
Instead of forcing programmers to use this roundabout technique if
nested functions are ever required, why aren't nested functions
supported directly?

It is commonly said that variables should be introduced into the
tightest scope possible. Why not extend the same to functions too?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]