[local_function] any interest in a LocalFunction library?

Hello all, Is there interest in a library that implement local functions for C++? Boost.LocalFunction (PROPOSAL DRAFT) This library allows to define and invoke a function locally within a code block. In addition to the parameters that can be passed to the function as usual upon its invocation, any variable within scope can be /binded/ to the local function declaration and used by the local function definition code. MOTIVATING EXAMPLE Consider the following example: #include <boost/local_function.hpp> class c { public: c(double const& x): x_(x) {} void f(double& x) { double y = x * 10.0; bool r; { double z = x * 100.0; // Local function definition. BOOST_LOCAL_FUNCTION( (bool) (l)( (char* const)(a) // Usual non-binded param. (bool)(b) // Another usual non-binded param. (binded)( (&x) // Binded param by reference. (const& x_) // Binded param by const reference. (y) // Binded param by value (copy). (const z) // Binded param by const value (copy) (const this) // Binded const object (by pointer). // (this) // Or, binded non-const object. ) ) ) { // Use `this_` here (not `this`) to access binded object. assert( this_->eq(x_) ); ... // Local function definition code. } BOOST_LOCAL_FUNCTION_END // Local function call only specifies non-binded params. bool r1 = BOOST_LOCAL_FUNCTION_CALL(l)("hello", true); bool r2 = BOOST_LOCAL_FUNCTION_CALL(l)("bye", false); r = r1 || r2; } // Local function goes out of scope here. ... } bool eq(double const& x) const { return x_ == x; } private: double x_; }; Note the following: 1) The local function `l` is only defined locally within a code block of the function `f`. 2) The parameter `x` of the function `f`, the member variable `x_`, the local variables `y` and `z`, and the object `this` are binded to the declaration of the local function. Therefore, they can all be used by the local function definition code even if they are not explicitly passed to the local function when it is invoked. (Also note that the binding syntax conveniently does not require the user to specify the types of the binded parameters but just their /binding-qualified/ names.) 3) The local function can be invoked (multiple times) from within the scope of its declaration. As usual, each invocation specifies the non-binded parameters and, for non-void functions, it returns the function result value. BACKGROUND I have not yet implemented Boost.LocalFunction. I will be implementing local-function features as part of Boost.Contract development (in order to support constant-correct block invariants and loop variants). I am probing for interest to understand how much effort I shall invest in making the local-function features a standalone library like Boost.LocalFunction separated from Boost.Contract. On Thu, Apr 15, 2010 at 7:02 PM, Alexander Nasonov <alnsn@yandex.ru> wrote:
vicente.botet wrote:
VBE> Boost.ScopeExit showed a technique that can be used to emulate local functions. Alexander proposed long time ago to provide it independently from ScopeExit but to my knowledge this has not been done.
Sorry for the late reply, I'm not following every boost thread, I got this message via google alerts.
Yes, this has not been done. Local function can borrow argument binding syntax from ScopeExit but there are other things I need to think of. For instance, in
int BOOST_LOCAL_FUNCTION(f, (BOOST_LOCAL_FUNCTION_BIND( (a)(&b) ), int c)) { // ... } BOOST_LOCAL_FUNCTION_END
syntax, is there any way to shorten BOOST_LOCAL_FUNCTION_BIND to "bind"?
The syntax doesn't have to be exactly as above. If someone could take a lead on this it would be great. I don't have time for this, I'm afraid.
The Boost.LocalFunction implementation will largely rely on parameter binding techniques similar to the ones currently used by Boost.ScopeExit as suggested to me by Steven Watanable, Vicente Botet, and Alexander Nasonov. Thank you. -- Lorenzo

What is the difference between boost.LocalFunction and lambda(or lambda+boost.Function)? -------------------------------------------------- From: "Lorenzo Caminiti" <lorcaminiti@gmail.com> Sent: Sunday, August 22, 2010 11:09 AM To: <boost@lists.boost.org> Subject: [boost] [local_function] any interest in a LocalFunction library?
Hello all,
Is there interest in a library that implement local functions for C++?
Boost.LocalFunction (PROPOSAL DRAFT)
This library allows to define and invoke a function locally within a code block. In addition to the parameters that can be passed to the function as usual upon its invocation, any variable within scope can be /binded/ to the local function declaration and used by the local function definition code.
MOTIVATING EXAMPLE
Consider the following example:
#include <boost/local_function.hpp>
class c { public: c(double const& x): x_(x) {}
void f(double& x) { double y = x * 10.0; bool r; { double z = x * 100.0;
// Local function definition. BOOST_LOCAL_FUNCTION( (bool) (l)( (char* const)(a) // Usual non-binded param. (bool)(b) // Another usual non-binded param. (binded)( (&x) // Binded param by reference. (const& x_) // Binded param by const reference. (y) // Binded param by value (copy). (const z) // Binded param by const value (copy) (const this) // Binded const object (by pointer). // (this) // Or, binded non-const object. ) ) ) { // Use `this_` here (not `this`) to access binded object. assert( this_->eq(x_) ); ... // Local function definition code. } BOOST_LOCAL_FUNCTION_END
// Local function call only specifies non-binded params. bool r1 = BOOST_LOCAL_FUNCTION_CALL(l)("hello", true); bool r2 = BOOST_LOCAL_FUNCTION_CALL(l)("bye", false);
r = r1 || r2; } // Local function goes out of scope here. ... }
bool eq(double const& x) const { return x_ == x; }
private: double x_; };
Note the following:
1) The local function `l` is only defined locally within a code block of the function `f`.
2) The parameter `x` of the function `f`, the member variable `x_`, the local variables `y` and `z`, and the object `this` are binded to the declaration of the local function. Therefore, they can all be used by the local function definition code even if they are not explicitly passed to the local function when it is invoked. (Also note that the binding syntax conveniently does not require the user to specify the types of the binded parameters but just their /binding-qualified/ names.)
3) The local function can be invoked (multiple times) from within the scope of its declaration. As usual, each invocation specifies the non-binded parameters and, for non-void functions, it returns the function result value.
BACKGROUND
I have not yet implemented Boost.LocalFunction. I will be implementing local-function features as part of Boost.Contract development (in order to support constant-correct block invariants and loop variants). I am probing for interest to understand how much effort I shall invest in making the local-function features a standalone library like Boost.LocalFunction separated from Boost.Contract.
On Thu, Apr 15, 2010 at 7:02 PM, Alexander Nasonov <alnsn@yandex.ru> wrote:
vicente.botet wrote:
VBE> Boost.ScopeExit showed a technique that can be used to emulate local functions. Alexander proposed long time ago to provide it independently from ScopeExit but to my knowledge this has not been done.
Sorry for the late reply, I'm not following every boost thread, I got this message via google alerts.
Yes, this has not been done. Local function can borrow argument binding syntax from ScopeExit but there are other things I need to think of. For instance, in
int BOOST_LOCAL_FUNCTION(f, (BOOST_LOCAL_FUNCTION_BIND( (a)(&b) ), int c)) { // ... } BOOST_LOCAL_FUNCTION_END
syntax, is there any way to shorten BOOST_LOCAL_FUNCTION_BIND to "bind"?
The syntax doesn't have to be exactly as above. If someone could take a lead on this it would be great. I don't have time for this, I'm afraid.
The Boost.LocalFunction implementation will largely rely on parameter binding techniques similar to the ones currently used by Boost.ScopeExit as suggested to me by Steven Watanable, Vicente Botet, and Alexander Nasonov.
Thank you.
-- Lorenzo _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On 8/22/2010 8:09 AM, Lorenzo Caminiti wrote:
Hello all,
Is there interest in a library that implement local functions for C++?
Boost.LocalFunction (PROPOSAL DRAFT)
This library allows to define and invoke a function locally within a code block. In addition to the parameters that can be passed to the function as usual upon its invocation, any variable within scope can be /binded/ to the local function declaration and used by the local function definition code. [...]
This looks interesting. My initial question is very superficial: Why did you choose the non-standard (to my knowledge) "binded", versus "bound" or simply "bind", as the keyword for bound (or, if you prefer, binded) parameters? - Jeff

I might be totally wrong here but I don't see how it's different from lambdas...

On Sun, Aug 22, 2010 at 11:18 AM, Mathieu - <ptr.jetable@gmail.com> wrote:
I might be totally wrong here but I don't see how it's different from lambdas...
What can it do differently from boost::phoenix? I am guessing you just create and instance a struct right there, but boost::phoenix would be more succinct.

On 8/22/2010 6:01 PM, OvermindDL1 wrote:
On Sun, Aug 22, 2010 at 11:18 AM, Mathieu -<ptr.jetable@gmail.com> wrote:
I might be totally wrong here but I don't see how it's different from lambdas...
What can it do differently from boost::phoenix? I am guessing you just create and instance a struct right there, but boost::phoenix would be more succinct.
Except Boost.Phoenix isn't as expressive as "real" C++, is it? E.g., local variables are somewhat clumsy (opinion) in the current incarnation of Boost.Phoenix. Also, it seems reasonable to implement BOOST_LOCAL_FUNCTION in terms of lambdas if they exist, but perhaps one would want to use local functions on non-lambda-enabled compilers. - Jeff

On Sun, Aug 22, 2010 at 7:27 PM, Jeffrey Lee Hellrung, Jr. <jhellrung@ucla.edu> wrote:
On 8/22/2010 6:01 PM, OvermindDL1 wrote:
On Sun, Aug 22, 2010 at 11:18 AM, Mathieu -<ptr.jetable@gmail.com> wrote:
I might be totally wrong here but I don't see how it's different from lambdas...
What can it do differently from boost::phoenix? I am guessing you just create and instance a struct right there, but boost::phoenix would be more succinct.
Except Boost.Phoenix isn't as expressive as "real" C++, is it? E.g., local variables are somewhat clumsy (opinion) in the current incarnation of Boost.Phoenix.
Also, it seems reasonable to implement BOOST_LOCAL_FUNCTION in terms of lambdas if they exist, but perhaps one would want to use local functions on non-lambda-enabled compilers.
True, local variable do require a unique construct, but that construct takes even less space then declaring multiple variables anyway (since essentially all variables in phoenix can be treated as 'auto'). And boost::phoenix does not use C++1x functionality, so it works on C98 compilers just fine, no C++ lambda's

On Sun, Aug 22, 2010 at 12:48 PM, Jeffrey Lee Hellrung, Jr. <jhellrung@ucla.edu> wrote:
On 8/22/2010 8:09 AM, Lorenzo Caminiti wrote:
Hello all,
Is there interest in a library that implement local functions for C++?
Boost.LocalFunction (PROPOSAL DRAFT)
This library allows to define and invoke a function locally within a code block. In addition to the parameters that can be passed to the function as usual upon its invocation, any variable within scope can be /binded/ to the local function declaration and used by the local function definition code.
[...]
This looks interesting. My initial question is very superficial: Why did you choose the non-standard (to my knowledge) "binded", versus "bound" or simply "bind", as the keyword for bound (or, if you prefer, binded) parameters?
I used "binded" because, obviously, I still don't know English :) I meant for it to be "bound". I'd use "bound" instead of "bind" because Boost.Parameter uses "deduced" instead of "deduce" (this might have to do with the keyword being used in declarative instead of imperative context... I had a similar discussion about C++0x "requires" but I still don't quite understand this argument...). However, this keyword could be anything that makes sense to the group... and given my limited English skills, I am happy to receive suggestions on what the keyword should be: 1) "bound" (my vote) 2) "bind" 3) Something else... what? Thanks a lot for pointing this out! -- Lorenzo

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost- bounces@lists.boost.org] On Behalf Of Lorenzo Caminiti Sent: Sunday, August 22, 2010 7:10 PM To: boost@lists.boost.org Subject: [boost] [local_function] any interest in a LocalFunction library?
Hello all,
Is there interest in a library that implement local functions for C++?
<snip> What's wrong with the following? Aside from the know limitations. (local::f cannot be a template arg or be a function template). void f() { struct local { static void f() {} }; local::f(); } Does your library have advantages over this? Regards, Dmitry

On 23/08/10 13:43, Dmitry Goncharov wrote:
What's wrong with the following? Aside from the know limitations. (local::f cannot be a template arg or be a function template). void f() { struct local { static void f() {} }; local::f(); }
Does your library have advantages over this?
I believe his macro has mechanisms for catching some variables in scope (at least, ScopeExit had). Something you would do with struct local { local(int j_) : j(j_) {} int operator()(int i) { return i + j; } private: int j; }; local f(j); could be written as something like LOCAL_FUNCTION_BEGIN(f, (j), (int i)) { return i + j; } LOCAL_FUNCTION_END Surely you would agree the second form is quite more succint

On Mon, Aug 23, 2010 at 10:05 AM, Mathias Gaunard <mathias.gaunard@ens-lyon.org> wrote:
On 23/08/10 13:43, Dmitry Goncharov wrote:
What's wrong with the following? Aside from the know limitations. (local::f cannot be a template arg or be a function template). void f() { struct local { static void f() {} }; local::f(); }
Does your library have advantages over this?
I believe his macro has mechanisms for catching some variables in scope (at least, ScopeExit had).
Something you would do with
struct local { local(int j_) : j(j_) {}
int operator()(int i) { return i + j; }
private: int j; }; local f(j);
could be written as something like
LOCAL_FUNCTION_BEGIN(f, (j), (int i)) { return i + j; } LOCAL_FUNCTION_END
Surely you would agree the second form is quite more succint
That is correct: The advantage of Boost.LocalFunction over simply using a static member of a local class is that Boost.LocalFunction supports binding of variables in scope (similarly to what Boost.ScopeExit does). In addition, note how the binding of `j` in the example above does not require you to specify its type (the example above just assumes `j` is `int` but Boost.LocalFunction, as well as Boost.ScopeExit, can automatically determine the type using typeof-like features). That is important because you might want to simply say "I am using the variable in scope `j` in my local function" without worrying about specifying its type. This type might change later and if it were specified explicitly also in the local function declaration it would require to change the code in multiple places making maintainance harder. Finally, note that the binding can be done by value (in which case the local function will use a copy of the binded variable with its value at the point of the local function declaration), or by reference (in which case the local function will use the current binded variable value at the point of the local function invocation), or by const value, or by const reference. -- Lorenzo

On Sun, Aug 22, 2010 at 11:09 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Is there interest in a library that implement local functions for C++?
I got a first version of Boost.LocalFunction implemented. The library uses just two macros `BOOST_LOCAL_FUNCTION()` and `BOOST_LOCAL_FUNCTION_END()`. The following example compiles (with both GCC and MSVC) on my development branch: #include <boost/local_function.hpp> #include <iostream> struct c { c(): y_(0.0) {} double f(double x) { int offset = x > 0 ? +100 : -100; BOOST_LOCAL_FUNCTION( (double) (line)( (int)(slope) (const bound)((&x)(offset)) (bound)((this)) ) ) { // x = 0; // Correctly errors because `x` is const-bound. double y = slope * x + offset; return this_->y_ = y; // OK because `this` is not const-bound. } BOOST_LOCAL_FUNCTION_END(line) return line(2); // Usual C++ function invocation syntax. } private: int y_; }; int main() { c cc; std::cout << cc.f(10) << std::endl; // Outputs `120`. return 0; } Note I changed the syntax a bit: 1) There are two separate bound parameter section one for const-bounds and another for non-const-bounds. (All local function parameters -- unbound, const-bound, non-const-bound -- are all optional.) 2) The `FUNCTION_END()` macro needs to repeat the local function name (the complier will error if this name does not match the one specified in the `FUNCTION()` macro). This repetition is not ideal but it allows me to create a functor object `line` to handle the local function so the local function can be invoked as usual by `line(2)` without using any additional `FUNCTION_CALL()` macro. In the example above: a) `x` is bound and implicitly passed to the local function as a const-reference. b) `offset` is bound and implicitly passed to the local function as a const-value. c) `this` is bound and implicitly passed to the local function as a non-const value (pointer) -- so the local function can change the object state `y_`. I need to write documentation, examples, and tests. (As I mentioned, the implementation of Boost.LocalFunction parameter binding vastly relies on Boost.ScopeExit internal mechanism to do the same thing.) -- Lorenzo

Lorenzo Caminiti wrote :
I got a first version of Boost.LocalFunction implemented.
1/ Sorry, I think I just realized I told you something wrong earlier on the list. One year ago, interest was raised towards unnamed local fonction. I missed that you were aiming for named function. we did not discuss named local function. As a consequence, I think it would be a great addition to your current work a version of the macro BOOST_LOCALFUNCTION macro that executes in place. It just needs a different macro name (ex: BOOST_IMMEDIATEFUNCTION), without the function name, without the function return type, and without the functor. So basically a wrapper around : { BOOST_SCOPE_EXIT() { } BOOST_SCOPE_EXIT_END(); } which binds also the 'this', and constness like you did, should do the trick. What do you think of this proposition? 2/ Is it possible to have look at your code? 3/ What is the generated code output by your example ? 4/ do you think your work could be use to allow Boost.ScopeExit to use your 'this' binding and constness techniques ? Best, Pierre Morcello

On Fri, Aug 27, 2010 at 1:39 PM, Pierre Morcello <pmorcell-cppfrance@yahoo.fr> wrote:
Lorenzo Caminiti wrote :
I got a first version of Boost.LocalFunction implemented.
1/ Sorry, I think I just realized I told you something wrong earlier on the list. One year ago, interest was raised towards unnamed local fonction. I missed that you were aiming for named function. we did not discuss named local function.
Do you have a link to that email thread? I would like to take a closer look at that discussion.
As a consequence, I think it would be a great addition to your current work a version of the macro BOOST_LOCALFUNCTION macro that executes in place. It just needs a different macro name (ex: BOOST_IMMEDIATEFUNCTION), without the function name, without the function return type, and without the functor.
So basically a wrapper around : { BOOST_SCOPE_EXIT() {
} BOOST_SCOPE_EXIT_END(); } which binds also the 'this', and constness like you did, should do the trick. What do you think of this proposition?
Yes but how is this different than just executing the code within a local code block `{ ... }`? Why is it necessary to wrap the code within the local function if the local function has no parameter and it is executed only once right after its definition? One (the only?) reason I can think of for local functions with no parameters and single immediate execution is to implement constant-correct code blocks -- which were my original need for local functions in Boost.Contract. For example: void f(int x) { int y = x; const { // Const-block but doesn't work in C++ :( assert(y == x); // Within const-block so compiler error if I mistake this with `y = x`. } ... } C++ does not support const-blocks `const { ... }` but local function's const-bound parameters can be used for that: void f(int x) { int y = x; { // Create inner scope so I can use the name `check()` multiple times without clashes. BOOST_LOCAL_FUNCTION( (void) (check)( (const bound)((&x)(&y)) ) ) { assert(y == x); // Now I get compiler error if I mistake this with `y = x`. } BOOST_LOCAL_FUNCTION_END(check) check(); // Execute immediately and just once. } ... } In fact, if I submit my Boost.LocalFunciton I will also propose and submit the macros `BOOST_CONST_BLOCK() / BOOST_CONST_BLOCK_END` to support const-blocks expanding to the local function code listed above. Using these macros the example above becomes: void f(int x) { int y = x; BOOST_CONST_BLOCK( (x)(y) ) { assert(y == x); // Now I get compiler error if I mistake this with `y = x`. } BOOST_CONST_BLOCK_END ... } (Note these macros alway and automatically bind the specified variables as `const&`.)
2/ Is it possible to have look at your code?
Of course and thanks for the interest! However, give me a couple of weeks so I can clean up the code and add a couple of examples. Then I will post a link to the source.
3/ What is the generated code output by your example ?
Same as above, I will post the code in a couple of weeks.
4/ do you think your work could be use to allow Boost.ScopeExit to use your 'this' binding and constness techniques ?
Yes, Boost.ScopeExit main macros can be now re-written using Boost.LocalFunction so to support both `const bound` parameters and `this`. I will add an example on how to implement Boost.ScopeExit using Boost.LocalFunction (really Boost.LocalFunction is implemented using all Boost.ScopeExit then just the outer macros so Boost.ScopeExit can be re-written using Boost.LocalFunction). -- Lorenzo

Sorry, I think I just realized I told you something wrong earlier on the list. One year ago, interest was raised towards unnamed local fonction. I missed that you were aiming for named function. we did not discuss named local function.
Do you have a link to that email thread? I would like to take a closer look at that discussion.
the beginning discussion was there : http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html and the point that interest you can be seen there : http://lists.boost.org/Archives/boost/2009/09/156126.php
Lorenzo Caminiti wrote : Why is it necessary to wrap the code within the local function if the local function has no parameter and it is executed only once right after its definition?
In that proposition, they are parameters (but not return types, neither function name). It was proposed to be able to use 'early return' (see the discussion link), as a complement for a 'Breakable' macro. Since the discussion was not clearly on local function, I had no clear interface, and I tested a lot of different looks/interfaces for the macro (like those you saw in my previous mail). I even tested named functions. I think you did better than I did in the end (I did not find how to transmit 'this' as you did + your interface is good ), well done! Still, unnamed void function with N parameters, that are called immediately are useful in certain cases (not always of course).
One (the only?) reason I can think of for local functions with no parameters and single immediate execution is to implement constant-correct code blocks -- which were my original need for local functions in Boost.Contract. For example:
void f(int x) { int y = x;
const { // Const-block but doesn't work in C++ :( assert(y == x); // Within const-block so compiler error if I mistake this with `y = x`. }
... }
I find it a very good idea! No need for std::equal_to etc... will make some code ligther. Thanks for your clear answers, Best, Pierre Morcello

On Tue, Aug 31, 2010 at 4:33 PM, Pierre Morcello <pmorcell-cppfrance@yahoo.fr> wrote:
Sorry, I think I just realized I told you something wrong earlier on the list. One year ago, interest was raised towards unnamed local fonction. I missed that you were aiming for named function. we did not discuss named local function.
Do you have a link to that email thread? I would like to take a closer look at that discussion.
the beginning discussion was there : http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html
and the point that interest you can be seen there : http://lists.boost.org/Archives/boost/2009/09/156126.php
Ok, I read the entire email thread. A couple of notes follow -- Boost.Breakable functionality would be provided by Boost.Block via `return;`. 1) Prompted by Alexander Nasonov questions, both David Abrahams and Vicente Botet expressed interest in "local functions with ScopeExit-like interface".
Re: [Boost.Breakable] Any interest in a Boost Breakable library? by Vicente Botet Escriba Sep 08, 2009; 10:39am :: Rate this Message: - Use ratings to moderate (?)? Reply | Print | View Threaded | Show Only this Message
David Abrahams-3 wrote: on Mon Sep 07 2009, Alexander Nasonov <alnsn-AT-yandex.ru> wrote:
Mathias Gaunard wrote:
What about using a lambda? [&]() -> void ... That kind of thing can also be made with macros instead of lambdas using a similar technique to that of Boost.ScopeExit.
Is there still an interest in local fuctions with ScopeExit-like interface?
I'm interested.
-- Dave Abrahams
While this interest was expressed in the context of unnamed lambda, Alexander question was not limited to unnamed local functions. I think the expressed interest applies 100% (if it is still there) to Boost.LocalFunction which is "(named) local functions with ScopeExit-like interface". However, interest from Alexander, Vicente, and possible Steven Watanabe (but I am not sure about David) is not a surprise because these are the people that suggested me to look into Boost.LocalFunction in the first place.
Still, unnamed void function with N parameters, that are called immediately are useful in certain cases (not always of course).
2) This functionality plus the one of Boost.Breakable-like breakability would be provided by Boost.Block in terms of both const and non-const blocks. I implemented Boost.Block using Boost.LocalFunction. Note that from within a Boost.Block, return jumps to the end of the block (and it does not exit the enclosing function) therefore also proving the Boost.Breakable functionality discussed in http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html. However, I am not sure if this "block breakability" via return is a feature or a limitation because users could expect `return;` to quit exit the enclosing function as usual and not just the local void-function used to implement the Boost.Block (only `return;` is allowed because the local function is void so if the enclosing function returns non-void this confusion does not exist). For example: #include <contract/detail/block.hpp> #include <contract/detail/local_function.hpp> #include <cassert> struct c { c(): x_(0.0) {} void f(int const& x) { // Non-const member function so `this` is not const. // Non-const block binds params all by `&` but with they original // `const` qualifier (i.e., `x` is `const&` but `this` is not const). CONTRACT_DETAIL_BLOCK( (this)(x) ) { if (x <= 0) return; // `return` jumps to block's end. this_->x_ = x; // OK, `f` (so `this`) is non-const member function. } CONTRACT_DETAIL_BLOCK_END // Const-block using the macros (preferred). // Params automatically bound as `const&` -- users do not specify `&`. CONTRACT_DETAIL_BLOCK_CONST( (this)(x) ) { // NOTE: Correctly, compiler error if `=` used instead of `==`. assert(this_->x_ == x); assert(x > 0 ); return; // Jump to block's end. assert(false); } CONTRACT_DETAIL_BLOCK_END { // Or, equivalently using the local function directly. CONTRACT_DETAIL_LOCAL_FUNCTION( (void) (block)( (const bound)((this)(&x)) ) ) { assert(this_->x_ == x); assert(x > 0 ); return; assert(false); } CONTRACT_DETAIL_LOCAL_FUNCTION_END(block) block(); // Execute code block immediately. } } private: int x_; }; However, the only use case I can think of for `BOOST_BLOCK` is to break to the block's end using `return;` and I have to say I was not convinced of the real existence of such a use case from the email thread http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html. The situation is much different for `BOOST_BLOCK_CONST` for which the use case is to add semantic information that a group of instructions should locally be executed in const-correct context so to allow the compiler to catch eventual programmers errors. At the end, using Boost.LocalFunction should be easy enough to program local functions taking parameters or not and to execute them immediately or not depending on your specific needs. -- Lorenzo

On Sun, Sep 12, 2010 at 2:47 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
2) This functionality plus the one of Boost.Breakable-like breakability would be provided by Boost.Block in terms of both const and non-const blocks.
I implemented Boost.Block using Boost.LocalFunction. Note that from within a Boost.Block, return jumps to the end of the block (and it does not exit the enclosing function) therefore also proving the Boost.Breakable functionality discussed in http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html. However, I am not sure if this "block breakability" via return is a feature or a limitation because users could expect `return;` to quit exit the enclosing function as usual and not just the local void-function used to implement the Boost.Block (only `return;` is allowed because the local function is void so if the enclosing function returns non-void this confusion does not exist). For example:
Actually, I just fixed this. If you try to use a `return` from within a Boost.Block code block you get this compiler error: error: return-statement with no value, in function returning ‘contract::detail::block::aux::ERROR_cannot_use_return_from_within_block’ The return type name should make it clear that you should not use return from the block so to avoid confusion with programmers using return from within a block attempting to exit the enclosing function. However, Boost.Block provides the macro `BOOST_BLOCK_BREAK` which can be used anywhere from within a code block to exit the block -- this is Boost.Breakable functionality (note that I do not feel strongly about this block-breakability feature, it was trivial so I added it to Boost.Block but I can also trivially remove the `BOOST_BLOCK_BREAK` if Booster don't want this feature). The following example now uses `BOOST_BLOCK_BREAK` instead of the `return;` (as the `return;` would have now generated the compiler error above):
#include <contract/detail/block.hpp> #include <contract/detail/local_function.hpp> #include <cassert>
struct c { c(): x_(0.0) {}
void f(int const& x) { // Non-const member function so `this` is not const.
// Non-const block binds params all by `&` but with they original // `const` qualifier (i.e., `x` is `const&` but `this` is not const). CONTRACT_DETAIL_BLOCK( (this)(x) ) { if (x <= 0) CONTRACT_DETAIL_BLOCK_BREAK; // `return` jumps to block's end. this_->x_ = x; // OK, `f` (so `this`) is non-const member function. } CONTRACT_DETAIL_BLOCK_END
// Const-block using the macros (preferred). // Params automatically bound as `const&` -- users do not specify `&`. CONTRACT_DETAIL_BLOCK_CONST( (this)(x) ) { // NOTE: Correctly, compiler error if `=` used instead of `==`. assert(this_->x_ == x); assert(x > 0 ); CONTRACT_DETAIL_BLOCK_BREAK; // Jump to block's end. assert(false); } CONTRACT_DETAIL_BLOCK_END
{ // Or, equivalently using the local function directly. CONTRACT_DETAIL_LOCAL_FUNCTION( (void) (block)( (const bound)((this)(&x)) ) ) { assert(this_->x_ == x); assert(x > 0 ); return; assert(false); } CONTRACT_DETAIL_LOCAL_FUNCTION_END(block) block(); // Execute code block immediately. } }
private: int x_; };
-- Lorenzo

<lorcaminiti@gmail.com> wrote:
Hello all,
Local functions are essentially implemented as member functions of local classes. These member functions do not have to be static and they could be virtual allowing for a local function to override one another.
However, I cannot understand if this overriding "feature" has any value at all... Have you ever used anything similar? Can you think of a use case for it?
I can't think of any.
this or this_ ?
I personnaly prefer this_ since it is a minor problem, and seems safer.
bound or bind?
I am ok with bound, or bind as long as there is no compatibility problems with boost::bind. It would be necessary to explain in the documentation that it is not the 'bind' of boost bind. 'closure' feels a bit long, while 'ref' would even sound better to my humble ears... but this is nothing fundamental to me neither.
Lorenzo wrote : This functionality plus the one of Boost.Breakable-like breakability would be provided by Boost.Block in terms of both const and non-const blocks. I implemented Boost.Block using Boost.LocalFunction. Note that from within a Boost.Block, return jumps to the end of the block (and it does not exit the enclosing function) therefore also proving the Boost.Breakable functionality discussed in http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html. However, I am not sure if this "block breakability" via return is a feature or a limitation because users could expect `return;` to quit exit the enclosing function as usual and not just the local void-function used to implement the Boost.Block
I am myself not convinced by your propositions on this point. If you present it like a 'block', when it's a local fuction directly called, then its more confusing than necessary. Concerning boost.breakable it was a very simple one liner, which happens to be useful in some cases. Concerning my earlier suggestion to add to your library was simply a local function called in-place (so presented as a local function). Of course, if you name it 'block' it is confusing. But if you use the term 'function' then it is ok for everyone to use 'return' and have a much easier interface. instead of : CONTRACT_DETAIL_BLOCK( (this)(x) ) { if (x <= 0) CONTRACT_DETAIL_BLOCK_BREAK; // `return` jumps to block's end. this_->x_ = x; // OK, `f` (so `this`) is non-const member function. } CONTRACT_DETAIL_BLOCK_END using something like : UNNAMED_FUNCTION( (this)(x) ) { if (x <= 0) return; this_->x_ = x; // OK, `f` (so `this`) is non-const member function. } UNNAMED_FUNCTION_END would be clearer in my humble opinion. You could replace UNNAMED_FUNCTION by DIRECT_FUNCTION or something else which clearly shows that it is a function. By the way, this was the interface used by the implementation I send you at the beginning (NESTED_FUNCTION + return) . Concerning the 'default' values that you proposed, it is an interesting idea, though I am not sure I would have a use for it. I consider you are doing a clean and serious work, keep on! Best regards, Pierre Morcello

On Mon, Sep 13, 2010 at 5:33 PM, Pierre Morcello <pmorcell-cppfrance@yahoo.fr> wrote:
<lorcaminiti@gmail.com> wrote:
Hello all,
Local functions are essentially implemented as member functions of local classes. These member functions do not have to be static and they could be virtual allowing for a local function to override one another.
However, I cannot understand if this overriding "feature" has any value at all... Have you ever used anything similar? Can you think of a use case for it?
I can't think of any.
this or this_ ?
I personnaly prefer this_ since it is a minor problem, and seems safer.
bound or bind?
I am ok with bound, or bind as long as there is no compatibility problems with boost::bind. It would be necessary to explain in the documentation that it is not the 'bind' of boost bind. 'closure' feels a bit long, while 'ref' would even sound better to my humble ears... but this is nothing fundamental to me neither.
Using `(bind)` has not issues with respect to `boost::bind`. That is because `(bind)` (or any other pp-keyword we end up selecting) has a meaning only for the preprocessor when the macro is expanded (so there is absolutely not relationship with `boost::bind`).
Lorenzo wrote : This functionality plus the one of Boost.Breakable-like breakability would be provided by Boost.Block in terms of both const and non-const blocks. I implemented Boost.Block using Boost.LocalFunction. Note that from within a Boost.Block, return jumps to the end of the block (and it does not exit the enclosing function) therefore also proving the Boost.Breakable functionality discussed in http://archives.free.net.ph/message/20090906.123719.b890ff7a.el.html. However, I am not sure if this "block breakability" via return is a feature or a limitation because users could expect `return;` to quit exit the enclosing function as usual and not just the local void-function used to implement the Boost.Block
I am myself not convinced by your propositions on this point. If you present it like a 'block', when it's a local fuction directly called, then its more confusing than necessary.
Concerning boost.breakable it was a very simple one liner, which happens to be useful in some cases.
Concerning my earlier suggestion to add to your library was simply a local function called in-place (so presented as a local function). Of course, if you name it 'block' it is confusing. But if you use the term 'function' then it is ok for everyone to use 'return' and have a much easier interface.
instead of :
CONTRACT_DETAIL_BLOCK( (this)(x) ) { if (x <= 0) CONTRACT_DETAIL_BLOCK_BREAK; // `return` jumps to block's end. this_->x_ = x; // OK, `f` (so `this`) is non-const member function. } CONTRACT_DETAIL_BLOCK_END
using something like :
UNNAMED_FUNCTION( (this)(x) ) { if (x <= 0) return; this_->x_ = x; // OK, `f` (so `this`) is non-const member function. } UNNAMED_FUNCTION_END
would be clearer in my humble opinion. You could replace UNNAMED_FUNCTION by DIRECT_FUNCTION or something else which clearly shows that it is a function. By the way, this was the interface used by the implementation I send you at the beginning (NESTED_FUNCTION + return) .
I agree, if the macro is named `..._FUNCTION` then `return` is not confusing. What is the use case for unnamed local functions? Is it just the breakable feature? Note that unnamed lambda are more useful because they can be defined at expression level. If an expression needs a functor, like `std::for_each()` call, then you defined it using lambda right where the functor is expected so you do not even need to name the lambda function -- but that use case does not apply to local functions that cannot be defined at the expression level. In order to use local function you have to name them and call them or pass them as functors to some other function... All in all, you can always just define a named local function and call if right away with one extra line of code: BOOST_LOCAL_FUNCTION( (void) (unamed)( (bound)((this)(&x)) ) ) { if (x <= 0) return; this_->x_ = x; } BOOST_LOCAL_FUNCTION_END(unamed) unamed(); I am not sure of the utility of unnamed local functions but if there is a clear use case for them, they would be really trivial to implement. I think what we need to find is a good use case for this. I was thinking to provide `BOOST_BLOCK` for "symmetry" because I will provide `BOOST_BLOCK_CONST` (as I said the use case for const-block is to add the semantic information about const-correctness of the enclosed instructions). I'll think about this more a propose something if I can find a use case then reviewers of the library can propose alternatives -- this stuff it's really trivial to implement around the basic `BOOST_LOCAL_FUNCTION` macros.
Concerning the 'default' values that you proposed, it is an interesting idea, though I am not sure I would have a use for it.
-- Lorenzo

On 14/09/10 03:52, Lorenzo Caminiti wrote:
I agree, if the macro is named `..._FUNCTION` then `return` is not confusing. What is the use case for unnamed local functions? Is it just the breakable feature? <snip> All in all, you can always just define a named local function and call if right away with one extra line of code:
BOOST_LOCAL_FUNCTION( (void) (unamed)( (bound)((this)(&x)) ) ) { if (x <= 0) return; this_->x_ = x; } BOOST_LOCAL_FUNCTION_END(unamed) unamed();
I am not sure of the utility of unnamed local functions but if there is a clear use case for them, they would be really trivial to implement. I think what we need to find is a good use case for this.
One thing that occurs to me is the possibly utility of unnamed local functions which are not void. For example, I sometimes want to have a variable which has to be non-const for a bit while I initialize it, but is then const (in principle). It would be nice to allow enforcing this (somewhat the reverse of BOOST_BLOCK_CONST). So, code like this: Foo y; y.setMagic(x); // y should not be changed hereafter which can be implemented using the stuff you've already offered as for example BOOST_LOCAL_FUNCTION( (Foo) (unamed)( (bound)((&x)) ) ) { Foo y; y.setMagic(x); return y; } BOOST_LOCAL_FUNCTION_END(unamed) Foo const y = unamed(); but is there value in providing dedicated functionality? e.g. there are three occurrences of 'Foo' there which might in theory by named only once. Another closely related issue is when you want to have an object briefly to pass to the constructor of another but destroy it soon afterwards (i.e. not have the order of construction be the reverse order of destruction); local functions could help there too. Right now I might do boost::scoped_ptr<Bar const> w(new Bar(x)); Foo y(*w); w.reset(); // Dispose of w soon, e.g. to free resources // Proceed to use y and never mention w again whereas with local functions I could do BOOST_LOCAL_FUNCTION( (Foo) (unamed)( (bound)((&x)) ) ) { Bar const w(x); return Foo(w); } BOOST_LOCAL_FUNCTION_END(unamed) Foo y = unamed(); and again it might be helpful to support this use case directly. I'm not convinced either of these (alone or together) is indeed worth a dedicated syntax, but they're other use cases to consider. In particular, these are cases where the name of the function doesn't really matter (and would be troublesome to settle on -- I'd probably use "make_y" or something similarly banal). John Bytheway

On 9/14/2010 2:25 PM, John Bytheway wrote:
On 14/09/10 03:52, Lorenzo Caminiti wrote:
I agree, if the macro is named `..._FUNCTION` then `return` is not confusing. What is the use case for unnamed local functions? Is it just the breakable feature? [...] I am not sure of the utility of unnamed local functions but if there is a clear use case for them, they would be really trivial to implement. I think what we need to find is a good use case for this.
One thing that occurs to me is the possibly utility of unnamed local functions which are not void. For example, I sometimes want to have a variable which has to be non-const for a bit while I initialize it, but is then const (in principle). It would be nice to allow enforcing this (somewhat the reverse of BOOST_BLOCK_CONST). [...] Another closely related issue is when you want to have an object briefly to pass to the constructor of another but destroy it soon afterwards (i.e. not have the order of construction be the reverse order of destruction); local functions could help there too. Right now I might do [...]
I think these are worthy use cases. I definitely find myself in these situations occasionally. - Jeff

On Tue, Sep 14, 2010 at 2:25 PM, John Bytheway <jbytheway+boost@gmail.com> wrote:
On 14/09/10 03:52, Lorenzo Caminiti wrote:
I agree, if the macro is named `..._FUNCTION` then `return` is not confusing. What is the use case for unnamed local functions? Is it just the breakable feature? <snip> All in all, you can always just define a named local function and call if right away with one extra line of code:
BOOST_LOCAL_FUNCTION( (void) (unamed)( (bound)((this)(&x)) ) ) { if (x <= 0) return; this_->x_ = x; } BOOST_LOCAL_FUNCTION_END(unamed) unamed();
I am not sure of the utility of unnamed local functions but if there is a clear use case for them, they would be really trivial to implement. I think what we need to find is a good use case for this.
One thing that occurs to me is the possibly utility of unnamed local functions which are not void. For example, I sometimes want to have a variable which has to be non-const for a bit while I initialize it, but is then const (in principle). It would be nice to allow enforcing this (somewhat the reverse of BOOST_BLOCK_CONST).
So, code like this:
Foo y; y.setMagic(x); // y should not be changed hereafter
which can be implemented using the stuff you've already offered as for example
BOOST_LOCAL_FUNCTION( (Foo) (unamed)( (bound)((&x)) ) ) { Foo y; y.setMagic(x); return y; } BOOST_LOCAL_FUNCTION_END(unamed) Foo const y = unamed();
but is there value in providing dedicated functionality? e.g. there are three occurrences of 'Foo' there which might in theory by named only once.
If you could pick, what would be your preferred syntax in this case?
Another closely related issue is when you want to have an object briefly to pass to the constructor of another but destroy it soon afterwards (i.e. not have the order of construction be the reverse order of destruction); local functions could help there too. Right now I might do
boost::scoped_ptr<Bar const> w(new Bar(x)); Foo y(*w); w.reset(); // Dispose of w soon, e.g. to free resources // Proceed to use y and never mention w again
whereas with local functions I could do
BOOST_LOCAL_FUNCTION( (Foo) (unamed)( (bound)((&x)) ) ) { Bar const w(x); return Foo(w); } BOOST_LOCAL_FUNCTION_END(unamed) Foo y = unamed();
and again it might be helpful to support this use case directly.
Again, if you could pick, what would be your preferred syntax in this case?
I'm not convinced either of these (alone or together) is indeed worth a dedicated syntax, but they're other use cases to consider. In particular, these are cases where the name of the function doesn't really matter (and would be troublesome to settle on -- I'd probably use "make_y" or something similarly banal).
Thanks for the examples. I am not sure I can provide a dedicated syntax due to the presence of `type var-name = ...` _after_ the local function declaration macros but if you (as well as other Boosters) propose an ideal macro syntax, I can see if I can implement something like that. -- Lorenzo

On 15/09/10 03:40, Lorenzo Caminiti wrote:
On Tue, Sep 14, 2010 at 2:25 PM, John Bytheway
BOOST_LOCAL_FUNCTION( (Foo) (unamed)( (bound)((&x)) ) ) { Foo y; y.setMagic(x); return y; } BOOST_LOCAL_FUNCTION_END(unamed) Foo const y = unamed();
but is there value in providing dedicated functionality? e.g. there are three occurrences of 'Foo' there which might in theory by named only once.
If you could pick, what would be your preferred syntax in this case?
Well, with C++0x lambdas it looks like (roughly, I haven't learnt this syntax properly yet): Foo const y = [&x]() { Foo y; y.setMagic(x); return y; } and it seems like we could come pretty close to that. Mimicking your existing syntax fairly closely would lead to: BOOST_INITIALIZE_FROM_FUNCTION( (Foo const)(y)((bound)((&x)))({ Foo y; y.setMagic(x); return y; }) ) but it occurs to me that these sort of functions would never need arguments (since you can't supply them), so I guess we could abbreviate it slightly, maybe to BOOST_INITIALIZE_FROM_FUNCTION( (Foo const)(y)((&x))({ Foo y; y.setMagic(x); return y; }) ) So, four things passed to the macro: - Type of declared variable. - Name of declared variable. - PP_SEQ of bindings (could make this optional). - Function body. Arguably the braces could be omitted too, but I think it's clearer to leave them. The macro will have to remove_const to deduce the return type for the local function. That makes me wonder whether you would also want to remove_reference, but it is not clear to me; I can't think of any use cases either way.
BOOST_LOCAL_FUNCTION( (Foo) (unamed)( (bound)((&x)) ) ) { Bar const w(x); return Foo(w); } BOOST_LOCAL_FUNCTION_END(unamed) Foo y = unamed();
and again it might be helpful to support this use case directly.
Again, if you could pick, what would be your preferred syntax in this case?
I think the exact same syntax works here, which is pleasing: BOOST_INITIALIZE_FROM_FUNCTION( (Foo)(y)((&x))({ Bar const w(x); return Foo(w); }) )
I'm not convinced either of these (alone or together) is indeed worth a dedicated syntax, but they're other use cases to consider. In particular, these are cases where the name of the function doesn't really matter (and would be troublesome to settle on -- I'd probably use "make_y" or something similarly banal).
Thanks for the examples. I am not sure I can provide a dedicated syntax due to the presence of `type var-name = ...` _after_ the local function declaration macros but if you (as well as other Boosters) propose an ideal macro syntax, I can see if I can implement something like that.
Well, I think the above is quite neat; apart from the massive macro name it's essentially as brief as using a lambda. Any other opinions? John Bytheway

On Mon, Sep 13, 2010 at 5:33 PM, Pierre Morcello <pmorcell-cppfrance@yahoo.fr> wrote:
Concerning the 'default' values that you proposed, it is an interesting idea, though I am not sure I would have a use for it.
Here's an example of how default parameters might be useful (together with recursion): #include <contract/detail/local_function.hpp> #include <iostream> #include <sstream> #include <algorithm> #include <vector> int main () { std::vector<int> v; v.push_back(1); v.push_back(4); v.push_back(7); std::ostringstream factorials; CONTRACT_DETAIL_LOCAL_FUNCTION( (int) (factorial)( (int)(n) (bool)(recursion)(default)(false) (bound)((&factorials)) ) ) { int result = 0; if (n < 2 ) result = 1; else result = n * factorial(n - 1, true); // Recursive call. if (!recursion) factorials << result << " "; return result; } CONTRACT_DETAIL_LOCAL_FUNCTION_END(factorial) std::for_each(v.begin(), v.end(), factorial); std::cout << factorials.str() << std::endl; return 0; } However, in general, default parameters are used to overload a function API. Therefore, I think they make much more sense when used in the public API as supposed in local functions which are in nature part of the implementation. (BTW, I just got the code above to work. It required quite a bit of re-work to get the template parameter trick to function together with default parameters...) -- Lorenzo

On Fri, Aug 27, 2010 at 1:39 PM, Pierre Morcello <pmorcell-cppfrance@yahoo.fr> wrote:
Lorenzo Caminiti wrote :
I got a first version of Boost.LocalFunction implemented. 2/ Is it possible to have look at your code?
You can find the source code at: http://dbcpp.svn.sourceforge.net/viewvc/dbcpp/trunk/src/contract/detail/ There are some tests and examples in: http://dbcpp.svn.sourceforge.net/viewvc/dbcpp/trunk/test/local_function_/ http://dbcpp.svn.sourceforge.net/viewvc/dbcpp/trunk/example/local_function_/ This is still a work in progress!! Tests/examples that bound `this` only work on GCC for now (because of MSVC error C2355 -- Boosters indicated a workaround but I still have to implement it). If the libraries in "contract/detail" were to be proposed to Boost: 1) Symbols will be renamed `CONTRACT_DETAIL` --> `BOOST_DETAIL`, `contract::detail` --> `boost::detail`, etc. 2) "contract/detail/local_function*" and "contract/detail/const_block*" will be proposed as Boost.LocalFunction and Boost.ConstBlock outside "boost/detail". The other supporting libraries in "contract/detail" will be proposed to be added to "boost/detail". 3) Another idea would be to add local functions and const-blocks to the existing Boost.ScopeExit library. Then Boost.ScopeExit could be renamed to Boost.Scope and the macros could be named `BOOST_SCOPE_EXIT`, `BOOST_SCOPE_FUNCTION`, `BOOST_SCOPE_CONST`, etc. (The current "boost/scope_exit.hpp" could still be kept for backward compatibility.) I don't really have a strong opinion between 2) and 3) but "local function" might be a better known to users than "scope function" so 2) might be a better option -- I am interested in what Boosters think.
3/ What is the generated code output by your example ?
::type &x ) { ((this_->x_ == x) ? (void)0 : __assert_func ("example/local_function_/const_block.cpp", 16, __PRETTY_FUNCTION__, "this_->x_ == x")); ((x > 0) ? (void)0 : __assert_func ("example/local_function_/const_block.cpp", 17, __PRETTY_FUNCTION__, "x > 0")); } }; } contract_detail_const_block_function_name_18_( contractXlocal_function_argsX.value); contract_detail_const_block_function_name_18_(); } { typedef void (*boost_se_tag_0_23)(int this_ ); typedef void (*boost_se_tag_1_23)(int &x ); typedef __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref(this, (boost_se_tag_0_23)0)))) boost_se_wrapped_t_0_23; typedef boost_se_wrapped_t_0_23::type boost_se_capture_t_0_23; typedef __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref(&x, (boost_se_tag_1_23)0)))) boost_se_wrapped_t_1_23; typedef boost_se_wrapped_t_1_23::type boost_se_capture_t_1_23; struct boost_se_params_t_23 { typedef boost_se_capture_t_0_23 boost_se_param_t_0_23; typedef boost_se_capture_t_1_23 boost_se_param_t_1_23; boost::scope_exit::aux::member< boost_se_param_t_0_23, boost_se_tag_0_23 > boost_se_param_0_23; boost::scope_exit::aux::member< boost_se_param_t_1_23, boost_se_tag_1_23 > boost_se_param_1_23; } contractXlocal_function_params_23X = { { boost::scope_exit::aux::deref(this, (boost_se_tag_0_23)0) } , { boost::scope_exit::aux::deref(&x, (boost_se_tag_1_23)0) } }; boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve< sizeof(contractXlocal_function_argsX) >::cmp1<0>::cmp2 > contractXlocal_function_argsX; contractXlocal_function_argsX.value = &contractXlocal_function_params_23X; class contractXlocal_function_functorXblockX { struct contractXlocal_function_castableX; public: contractXlocal_function_functorXblockX(void* bound_params) : contractXlocal_function_paramsX( (boost_se_params_t_23*) bound_params) {} void operator()( ) { return contractXlocal_function_castableX:: contractXlocal_function_bodyX ( contractXlocal_function_paramsX-> boost_se_param_0_23.value , contractXlocal_function_paramsX-> boost_se_param_1_23.value ); } private: boost_se_params_t_23* contractXlocal_function_paramsX; struct contractXlocal_function_castableX { static void contractXlocal_function_bodyX( ::contract::detail::add_pointed_const< boost_se_params_t_23:: boost_se_param_t_0_23 >::type this_ , ::boost::add_const< boost_se_params_t_23:: boost_se_param_t_1_23 ::type &x ) { ((this_->x_ == x) ? (void)0 : __assert_func ("example/local_function_/const_block.cpp", 24, __PRETTY_FUNCTION__, "this_->x_ == x")); ((x > 0) ? (void)0 : __assert_func ("example/local_function_/const_block.cpp", 25, __PRETTY_FUNCTION__, "x > 0")); } }; }; contractXlocal_function_functorXblockX block( contractXlocal_function_argsX.value); block(); } }
This example for both const-block and local function: #include <contract/detail/local_function.hpp> #include <contract/detail/const_block.hpp> #include <cassert> struct c { c(): x_(0.0) {} void f(int x) { x_ = x; // Const-block using the macros (preferred). // Params automatically bound as `const&` -- user doesn't specify `&`. CONTRACT_DETAIL_CONST_BLOCK( (this)(x) ) { // NOTE: Correctly compiler error if `=` used instead of `==`. assert(this_->x_ == x); assert(x > 0 ); } CONTRACT_DETAIL_CONST_BLOCK_END { // Or, equivalently using the local function directly. CONTRACT_DETAIL_LOCAL_FUNCTION( (void) (block)( (const bound)((this)(&x)) ) ) { assert(this_->x_ == x); assert(x > 0 ); } CONTRACT_DETAIL_LOCAL_FUNCTION_END(block) block(); // Execute block code immediately. } } private: int x_; }; int main() { c cc; cc.f(1); return 0; } Expands to: ... struct c { c(): x_(0.0) {} void f(int x) { x_ = x; { typedef void (*boost_se_tag_0_14)(int this_ ); typedef void (*boost_se_tag_1_14)(int &x ); typedef __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref(this, (boost_se_tag_0_14)0)))) boost_se_wrapped_t_0_14; typedef boost_se_wrapped_t_0_14::type boost_se_capture_t_0_14; typedef __typeof__(boost::type_of::ensure_obj(boost::scope_exit::aux::wrap( boost::scope_exit::aux::deref(&x, (boost_se_tag_1_14)0)))) boost_se_wrapped_t_1_14; typedef boost_se_wrapped_t_1_14::type boost_se_capture_t_1_14; struct boost_se_params_t_14 { typedef boost_se_capture_t_0_14 boost_se_param_t_0_14; typedef boost_se_capture_t_1_14 boost_se_param_t_1_14; boost::scope_exit::aux::member< boost_se_param_t_0_14, boost_se_tag_0_14 > boost_se_param_0_14; boost::scope_exit::aux::member< boost_se_param_t_1_14, boost_se_tag_1_14 > boost_se_param_1_14; } contractXlocal_function_params_14X = { { boost::scope_exit::aux::deref(this, (boost_se_tag_0_14)0) } , { boost::scope_exit::aux::deref(&x, (boost_se_tag_1_14)0) } }; boost::scope_exit::aux::declared< boost::scope_exit::aux::resolve< sizeof(contractXlocal_function_argsX) >::cmp1<0>::cmp2 > contractXlocal_function_argsX; contractXlocal_function_argsX.value = &contractXlocal_function_params_14X; class contractXlocal_function_functorXcontract_detail_const_block_function_name_14_X { struct contractXlocal_function_castableX; public: contractXlocal_function_functorXcontract_detail_const_block_function_name_14_X(void* bound_params) : contractXlocal_function_paramsX( (boost_se_params_t_14*) bound_params) {} void operator()( ) { return contractXlocal_function_castableX:: contractXlocal_function_bodyX ( contractXlocal_function_paramsX-> boost_se_param_0_14.value , contractXlocal_function_paramsX-> boost_se_param_1_14.value ); } private: boost_se_params_t_14* contractXlocal_function_paramsX; struct contractXlocal_function_castableX { static void contractXlocal_function_bodyX( ::contract::detail::add_pointed_const< boost_se_params_t_14:: boost_se_param_t_0_14 >::type this_ , ::boost::add_const< boost_se_params_t_14:: boost_se_param_t_1_14 private: int x_; }; int main() { c cc; cc.f(1); return 0; } -- Lorenzo

On Sun, Aug 22, 2010 at 11:09 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Is there interest in a library that implements local functions for C++?
BTW, I just realized that I never mentioned it before but Boost.LocalFunction also supports default values for unbound parameters. For example, the unbound `offset` parameter of the `line()` local function below is optional (its default value is `0`): #include <contract/detail/local_function.hpp> #include <iostream> struct c { c(): y_(0.0) {} void f(double x) { CONTRACT_DETAIL_LOCAL_FUNCTION( (double) (line)( (int)(slope) (int)(offset)(default)(0) // Has default value. (const bound)((&x)) (bound)((this)) ) ) { double y = slope * x + offset; return this_->y_ = y; } CONTRACT_DETAIL_LOCAL_FUNCTION_END(line) std::cout << line(2) << std::endl; // Print `20`. std::cout << line(2, 100) << std::endl; // Print `120`. } private: double y_; }; int main() { c cc; cc.f(10); return 0; } -- Lorenzo

On Sun, Aug 22, 2010 at 11:09 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Is there interest in a library that implement local functions for C++?
Boost.LocalFunction (PROPOSAL DRAFT)
Hello all, Based on our discussions so far (thanks a lot for all the input!) I am starting to make some actual design decisions. These decisions are not final and they are of course subject to continuous improvement and necessary changes that will be identified by Boosters during the formal review of the library. However, for the current development stage of the library I will make these decisions and move forward (otherwise I keep changing things forever). If you have a strong opinion on any of these topics, please voice your opinion _now_ so to minimize the amount of my re-work later :) CURRENT STATUS 1) I will name the library Boost.Local and this will include local functions (BOOST_LOCAL_FUNCTION/BOOST_LOCAL_FUNCTION_END/BOOST_LOCAL_FUNCTION_END_RENAME) as well as local constant blocks (BOOST_LOCAL_CONST/BOOST_LOCAL_CONST_END). 2) I will require users to use `this_` instead of `this` inside local functions when the enclosing object is bound. The local function is internally implement as a _static_ member of a local class so `this` will simply not be available and it cannot be used by mistake instead of `this_`. 3) I will use the `bind` preprocessor "keyword" for the parenthesized syntax as in `(bind)(...)` and `(const bind)(...)`. `bind` is more readable than `bound` or `closure` (plus I do not know English well enough to figure out if `bound` is more correct because it is used in declarative as supposed as imperative context... English native speakers: Help me!). 4) Local functions will use a trick that will allow them to be passed as template parameters (this is not possible for plain member functions of local classes). This will allow to pass local functions to algorithms like `std::for_each` which is a major use case of C++0x lambdas. (Still local functions will suffer the important limitations that they cannot be defined at expression level and they cannot have template parameters.) 5) When used within a template, the macros `BOOST_LOCAL_FUNCTION_TPL`, `BOOST_LOCAL_CONST_TPL`, etc will need to be used (otherwise you get a compiler error). This is necessary for the library to apply `typename` from within the template where the type determination is context depend (and given that C++ does not allow to use `typename` outside templates). The same convention is used by Boost.ScopeExit, etc. 6) Local functions will support recursion. 7) Local functions will support optional default values for non-bound parameters (as usual for C++ functions). 8) I will not provide the `BOOST_LOCAL_BLOCK` but only the `BOOST_LOCAL_CONST`. The only reason for `BOOST_LOCAL_BLOCK` would be to break to its exit using `return` and a local function executed immediately after it is defined can be used for that purpose. 9) I will not allow a local function to "inherit" from another local function. It seems there is no use case for such a feature (and I am not really sure how to define this behavior in the first place because inheritance makes sense between objects and not between functions... see related Boost email thread). 10) I will not merge Boost.Local with Boost.ScopeExit into a more generic Boost.Scope library. However, I will provide macros `BOOST_LOCAL_EXIT/BOOST_LOCAL_EXIT_END` which will work like Boost.ScopeExit plus they will allow to bind `this`. Boost.ScopeExit does not allow to bind `this` correct? OPEN ISSUES a) I am not sure if local functions can be nested into one another. In other words, I do not yet know if it will be possible to define a local function from within another local function. b) I am not sure if I will provide unnamed local functions (void or not) and if so what their syntax will look like. It seems if you need this you can just use the local functions macros to program it without a dedicated syntax (but still discussing...). c) I am not sure if I will provide local functions that execute immediately after they are defined. This might relate to b). Again, if you need this you can simply call the local function right after you define it without a dedicated syntax (but still discussing...). (I will eventually document all these points, and more, in the library documentation under the "Rational" section.) -- Lorenzo

On Wed, Sep 15, 2010 at 10:56 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Sun, Aug 22, 2010 at 11:09 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Is there interest in a library that implement local functions for C++?
Boost.LocalFunction (PROPOSAL DRAFT)
Hello all,
Based on our discussions so far (thanks a lot for all the input!) I am starting to make some actual design decisions. These decisions are not final and they are of course subject to continuous improvement and necessary changes that will be identified by Boosters during the formal review of the library. However, for the current development stage of the library I will make these decisions and move forward (otherwise I keep changing things forever).
If you have a strong opinion on any of these topics, please voice your opinion _now_ so to minimize the amount of my re-work later :)
CURRENT STATUS
1) I will name the library Boost.Local and this will include local functions (BOOST_LOCAL_FUNCTION/BOOST_LOCAL_FUNCTION_END/BOOST_LOCAL_FUNCTION_END_RENAME) as well as local constant blocks (BOOST_LOCAL_CONST/BOOST_LOCAL_CONST_END).
2) I will require users to use `this_` instead of `this` inside local functions when the enclosing object is bound. The local function is internally implement as a _static_ member of a local class so `this` will simply not be available and it cannot be used by mistake instead of `this_`.
3) I will use the `bind` preprocessor "keyword" for the parenthesized syntax as in `(bind)(...)` and `(const bind)(...)`. `bind` is more readable than `bound` or `closure` (plus I do not know English well enough to figure out if `bound` is more correct because it is used in declarative as supposed as imperative context... English native speakers: Help me!).
4) Local functions will use a trick that will allow them to be passed as template parameters (this is not possible for plain member functions of local classes). This will allow to pass local functions to algorithms like `std::for_each` which is a major use case of C++0x lambdas. (Still local functions will suffer the important limitations that they cannot be defined at expression level and they cannot have template parameters.)
5) When used within a template, the macros `BOOST_LOCAL_FUNCTION_TPL`, `BOOST_LOCAL_CONST_TPL`, etc will need to be used (otherwise you get a compiler error). This is necessary for the library to apply `typename` from within the template where the type determination is context depend (and given that C++ does not allow to use `typename` outside templates). The same convention is used by Boost.ScopeExit, etc.
6) Local functions will support recursion.
7) Local functions will support optional default values for non-bound parameters (as usual for C++ functions).
8) I will not provide the `BOOST_LOCAL_BLOCK` but only the `BOOST_LOCAL_CONST`. The only reason for `BOOST_LOCAL_BLOCK` would be to break to its exit using `return` and a local function executed immediately after it is defined can be used for that purpose.
9) I will not allow a local function to "inherit" from another local function. It seems there is no use case for such a feature (and I am not really sure how to define this behavior in the first place because inheritance makes sense between objects and not between functions... see related Boost email thread).
10) I will not merge Boost.Local with Boost.ScopeExit into a more generic Boost.Scope library. However, I will provide macros `BOOST_LOCAL_EXIT/BOOST_LOCAL_EXIT_END` which will work like Boost.ScopeExit plus they will allow to bind `this`. Boost.ScopeExit does not allow to bind `this` correct?
OPEN ISSUES
a) I am not sure if local functions can be nested into one another. In other words, I do not yet know if it will be possible to define a local function from within another local function.
b) I am not sure if I will provide unnamed local functions (void or not) and if so what their syntax will look like. It seems if you need this you can just use the local functions macros to program it without a dedicated syntax (but still discussing...).
c) I am not sure if I will provide local functions that execute immediately after they are defined. This might relate to b). Again, if you need this you can simply call the local function right after you define it without a dedicated syntax (but still discussing...).
(I will eventually document all these points, and more, in the library documentation under the "Rational" section.)
As of right now, local function will be implemented more or less using the following skeleton code (many thanks to John Bytheway for refining my global base functors trick): #include <iostream> #include <algorithm> #include <vector> // Must be global type so lfn inheriting from this can be passed as tparam. template<typename F> struct lfn_ftor_base {}; template<typename R, typename A1> struct lfn_ftor_base<R (A1)> // Abstract so never returns R (R could be void, have no default ctor, etc). { virtual R operator()(A1) = 0; }; // Wrap lfn functor ref in global type so it can be passed as tparm. template<typename F> struct lfn_ftor_ref {}; template<typename R, typename A1> struct lfn_ftor_ref<R (A1)> { typedef R (f_type)(A1); explicit lfn_ftor_ref(lfn_ftor_base<f_type>& ftor): ftor_(ftor) {} inline R operator()(A1 a1) { return ftor_(a1); } private: lfn_ftor_base<f_type>& ftor_; }; int main () { double x = 5.6; // BOOST_LOCAL_FUNCTION( // (inline) (void) (lfn)( (int)(i) (const bound)((&x)) ) // ) { // std::cout << " " << i + x; // if (i > 0) lfn(-i); // Recursive call. // } BOOST_LOCAL_FUNCTION_END(lfn) // Implementation of a local function named `lfn`. struct lfn_ftor: lfn_ftor_base<void (int)> { typedef void (f_type)(int); explicit lfn_ftor(double const& x): bound_x_(x) {} // Implement abstract base functor. inline void operator()(int i) { lfn(i); } private: // Bound params hold in a member variable (this example hides all // ScopeExit-like bound param type determination code). double const& bound_x_; // Member with local func name to allow recursion. inline void lfn(int i) { body(i, bound_x_); } // Body func cannot be static to allow recursive calls to `lfn` // (limitation: `this` available also when `this_` should be used). // Ultimately, bound params must be passed as func param because their // name is not know to preprocessor (it can prefixed by `&`). inline void body(int i, double const& x) { std::cout << " " << i + x; if (i > 0) lfn(-i); // Recursive call. } }; lfn_ftor lfn_obj(x); // x is const& bound from scope. lfn_ftor_ref<lfn_ftor::f_type> lfn(lfn_obj); std::vector<int> v; v.push_back(10); v.push_back(20); v.push_back(30); std::cout << "v: "; std::for_each(v.begin(), v.end(), lfn); std::cout << std::endl; return 0; } -- Lorenzo

On 15/09/10 18:55, Lorenzo Caminiti wrote:
As of right now, local function will be implemented more or less using the following skeleton code (many thanks to John Bytheway for refining my global base functors trick):
You're welcome :). I will say that you may wish to switch back from operator() to a named function (for the sake of clarity). I only switched to operator() because I thought it would allow use of boost::ref (which it doesn't). John

On Wed, Sep 15, 2010 at 10:56 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Sun, Aug 22, 2010 at 11:09 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Is there interest in a library that implement local functions for C++?
This example compiles on both GCC and MSVC, and it shows a few features of the library: #include <contract/detail/local_function.hpp> #include <iostream> #include <algorithm> #include <vector> int main () { int offset = 5; std::vector<int> v; std::vector<int> w; // v = 10 20 30 40 50 for (int i = 1; i < 6; i++) v.push_back(i * 10); w.resize(v.size()); // w = ++v + 5 = 16 26 36 46 56 CONTRACT_DETAIL_LOCAL_FUNCTION( (int) (inc)( (int)(i) (const bind)((&offset)) ) ) { // Compiler error if const `offset` modified here by mistake. return ++i + offset; } CONTRACT_DETAIL_LOCAL_FUNCTION_END(inc) // `offset` is 5 for this invocation of `inc()`. std::transform(v.begin(), v.end(), w.begin(), inc); // v = ++(v + w) + 0 = 27 47 67 87 107 CONTRACT_DETAIL_LOCAL_FUNCTION( (int) (inc_sum)( (int)(i) (int)(j) (bind)((inc)) ) ) { return inc(i + j); } CONTRACT_DETAIL_LOCAL_FUNCTION_END(inc_sum) offset = 0; // No offset for this invocation of `inc()` via `inc_sum()`. std::transform(v.begin(), v.end(), w.begin(), v.begin(), inc_sum); for (std::vector<int>::iterator i = v.begin(); i != v.end(); ++i) std::cout << " " << *i; std::cout << std::endl; return 0; } Note: 1) The local function `inc()` is bound to the second local function `inc_sum()` so `inc()` can be called by `inc_sum()`. 2) `offset` is bound as `const` so it cannot be modified within the local function `inc()`. 3) However, `offset` is bound as a reference `&` so its value is 5 when `inc()` is called by the 1st `std::transform()` but then its value is set to 0 by the enclosing function for when it is called a second time by the `inc_sum()` as part of the 2nd `std::transform()` call. 4) Local functions are passed as template parameters to `std::transform()`. None of this can be done using the simpler construct: void f() { struct local_function { static result-type body(param-list) { ... } }; ... } -- Lorenzo

On 15/09/10 15:56, Lorenzo Caminiti wrote:
2) I will require users to use `this_` instead of `this` inside local functions when the enclosing object is bound. The local function is internally implement as a _static_ member of a local class so `this` will simply not be available and it cannot be used by mistake instead of `this_`.
I'm puzzled; you say you're using static functions here but the examples you give don't, and in particular this seems incompatible with the "pass as template parameters" trick and recursion.
3) I will use the `bind` preprocessor "keyword" for the parenthesized syntax as in `(bind)(...)` and `(const bind)(...)`. `bind` is more readable than `bound` or `closure` (plus I do not know English well enough to figure out if `bound` is more correct because it is used in declarative as supposed as imperative context... English native speakers: Help me!).
I think it can be interpreted as either imperative (instructing the macro to bind things) or declarative (stating that the things are bound). I wouldn't worry too much.
5) When used within a template, the macros `BOOST_LOCAL_FUNCTION_TPL`, `BOOST_LOCAL_CONST_TPL`, etc will need to be used (otherwise you get a compiler error). This is necessary for the library to apply `typename` from within the template where the type determination is context depend (and given that C++ does not allow to use `typename` outside templates). The same convention is used by Boost.ScopeExit, etc.
I think C++0x allows the typename keyword in more contexts, so you might be able to get away with it having only one variety there. Probably not worth the trouble, though, given that the library is somewhat made obsolete by C++0x features anyway... John Bytheway

On 9/15/2010 10:56 AM, Lorenzo Caminiti wrote:
On Sun, Aug 22, 2010 at 11:09 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
Hello all,
Is there interest in a library that implement local functions for C++?
Boost.LocalFunction (PROPOSAL DRAFT)
Hello all,
Based on our discussions so far (thanks a lot for all the input!) I am starting to make some actual design decisions. These decisions are not final and they are of course subject to continuous improvement and necessary changes that will be identified by Boosters during the formal review of the library. However, for the current development stage of the library I will make these decisions and move forward (otherwise I keep changing things forever).
If you have a strong opinion on any of these topics, please voice your opinion _now_ so to minimize the amount of my re-work later :)
CURRENT STATUS
1) I will name the library Boost.Local and this will include local functions (BOOST_LOCAL_FUNCTION/BOOST_LOCAL_FUNCTION_END/BOOST_LOCAL_FUNCTION_END_RENAME) as well as local constant blocks (BOOST_LOCAL_CONST/BOOST_LOCAL_CONST_END).
The name seems reasonable.
2) I will require users to use `this_` instead of `this` inside local functions when the enclosing object is bound. The local function is internally implement as a _static_ member of a local class so `this` will simply not be available and it cannot be used by mistake instead of `this_`.
3) I will use the `bind` preprocessor "keyword" for the parenthesized syntax as in `(bind)(...)` and `(const bind)(...)`. `bind` is more readable than `bound` or `closure` (plus I do not know English well enough to figure out if `bound` is more correct because it is used in declarative as supposed as imperative context... English native speakers: Help me!).
4) Local functions will use a trick that will allow them to be passed as template parameters (this is not possible for plain member functions of local classes). This will allow to pass local functions to algorithms like `std::for_each` which is a major use case of C++0x lambdas. (Still local functions will suffer the important limitations that they cannot be defined at expression level and they cannot have template parameters.)
This could be very convenient. Be sure to address the performance issues when using such a construct (I am myself curious; it seems that John's done some preliminary work).
5) When used within a template, the macros `BOOST_LOCAL_FUNCTION_TPL`, `BOOST_LOCAL_CONST_TPL`, etc will need to be used (otherwise you get a compiler error). This is necessary for the library to apply `typename` from within the template where the type determination is context depend (and given that C++ does not allow to use `typename` outside templates). The same convention is used by Boost.ScopeExit, etc.
I'm sorry, but in what context are these macros necessary?
6) Local functions will support recursion.
How would that be effected?
7) Local functions will support optional default values for non-bound parameters (as usual for C++ functions).
Might as well.
8) I will not provide the `BOOST_LOCAL_BLOCK` but only the `BOOST_LOCAL_CONST`. The only reason for `BOOST_LOCAL_BLOCK` would be to break to its exit using `return` and a local function executed immediately after it is defined can be used for that purpose.
I think, if only for completeness and symmetry, something equivalent to BOOST_LOCAL_BLOCK should be provided.
9) I will not allow a local function to "inherit" from another local function. It seems there is no use case for such a feature (and I am not really sure how to define this behavior in the first place because inheritance makes sense between objects and not between functions... see related Boost email thread).
10) I will not merge Boost.Local with Boost.ScopeExit into a more generic Boost.Scope library. However, I will provide macros `BOOST_LOCAL_EXIT/BOOST_LOCAL_EXIT_END` which will work like Boost.ScopeExit plus they will allow to bind `this`. Boost.ScopeExit does not allow to bind `this` correct?
Perhaps the Boost.ScopeExit macros can simply be implemented in terms of BOOST_LOCAL_* macros...? Seems silly to ultimately retain duplicate copies of the same implementation.
OPEN ISSUES
a) I am not sure if local functions can be nested into one another. In other words, I do not yet know if it will be possible to define a local function from within another local function.
What are the issues you're running into?
b) I am not sure if I will provide unnamed local functions (void or not) and if so what their syntax will look like. It seems if you need this you can just use the local functions macros to program it without a dedicated syntax (but still discussing...).
I think this, like the BOOST_LOCAL_BLOCK macro, is mildly useful, trivial to implement given the already-proposed functionality, and benefits from having a standardized macro. My feeling is to include this functionality.
c) I am not sure if I will provide local functions that execute immediately after they are defined. This might relate to b). Again, if you need this you can simply call the local function right after you define it without a dedicated syntax (but still discussing...).
How is this different from (b), exactly? I.e., it doesn't seem possible to create an unnamed local function and execute it sometime later...
(I will eventually document all these points, and more, in the library documentation under the "Rational" section.)
Excellent. - Jeff

On Wed, Sep 15, 2010 at 10:56 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
8) I will not provide the `BOOST_LOCAL_BLOCK` but only the `BOOST_LOCAL_CONST`. The only reason for `BOOST_LOCAL_BLOCK` would be to break to its exit using `return` and a local function executed immediately after it is defined can be used for that purpose.
I have decided to provide a single block macro `BOOST_LOCAL_BLOCK` which allows to bind both const and non const so the users can decide which bound variables need to be cons within the block and which do not. If you want a pure const-block then you'll simply bind all variable as `const&`. Blocks of course execute in-place right where they are defined. I have also kept the block break feature via the macro `BOOST_LOCAL_BLOCK_BREAK` (you get a compiler error if you just try to use `return`). For example (this compiles and works): #include <contract/detail/local/block.hpp> #include <cassert> struct c { c(): x_(0.0) {} void f(int& x) { // Non-const member function so `this` is not const. // Non-const `this` but const `x`. CONTRACT_DETAIL_LOCAL_BLOCK( (const bind)((&x)) (bind)((this)) ) { this_->x_ = x; // Non-const `this` cant be modified. assert(x == this_->x_); // Compiler error if `=` instead of `==`. CONTRACT_DETAIL_LOCAL_BLOCK_BREAK; // Jump to block's end. assert(false); // Never executed. } CONTRACT_DETAIL_LOCAL_BLOCK_END x = x_; // Non-const `x` changed outside block. } private: int x_; }; int main() { c cc; int x = 1; cc.f(x); return 0; } -- Lorenzo

Hi Lorenzo,
Lorenzo Caminiti wrote : I have decided to provide a single block macro `BOOST_LOCAL_BLOCK` which allows to bind both const and non const so the users can decide which bound variables need to be cons within the block and which do not. If you want a pure const-block then you'll simply bind all variable as `const&`. Blocks of course execute in-place right where they are defined. I have also kept the block break feature via the macro `BOOST_LOCAL_BLOCK_BREAK` (you get a compiler error if you just try to use `return`).
I would have prefered to see the FUNCTION + 'return' personnally. But, I think I get your point : local unnamed macro function can be generated easily from your local named function. I made some tests to check and this seems ok for me, as long as several local classes can share the same name in a function. Here is an example of what I mean : void TestDoubleLocalFunc::aFunction(void) { { class unnamed { public: int that; } something; something.that = 1; } { class unnamed { public: std::string those; } something; something.those = ""; } } This use 2 local classes with the same name. It did compile under VS2008, however is it tolerated in C++ standard ? If not, I would prefer that you provide an unnamed local function macro which does not require the user to write once more the name of the function in LOCAL_FUNCTION_END(nameOfTheFunction). This is doable (see the first code I sent you), and would allow to write the name of the function only once, and not require it several times as in your actual LOCAL_FUNCTION macros. Best, Pierre

On Thu, Sep 16, 2010 at 6:32 PM, Pierre Morcello <pmorcell-cppfrance@yahoo.fr> wrote:
Hi Lorenzo,
Lorenzo Caminiti wrote : I have decided to provide a single block macro `BOOST_LOCAL_BLOCK` which allows to bind both const and non const so the users can decide which bound variables need to be cons within the block and which do not. If you want a pure const-block then you'll simply bind all variable as `const&`. Blocks of course execute in-place right where they are defined. I have also kept the block break feature via the macro `BOOST_LOCAL_BLOCK_BREAK` (you get a compiler error if you just try to use `return`).
I would have prefered to see the FUNCTION + 'return' personnally. But, I think I get your point : local unnamed macro function can be generated easily from your local named function. I made some tests to check and this seems ok for me, as long as several local classes can share the same name in a function.
Here is an example of what I mean :
void TestDoubleLocalFunc::aFunction(void) { { class unnamed { public: int that; } something; something.that = 1;
} { class unnamed { public: std::string those; } something; something.those = ""; } }
This use 2 local classes with the same name. It did compile under VS2008, however is it tolerated in C++ standard ? If not, I would prefer that you provide an unnamed local function macro which does not require the user to write once more the name of the function in LOCAL_FUNCTION_END(nameOfTheFunction). This is doable (see the first code I sent you), and would allow to write the name of the function only once, and not require it several times as in your actual LOCAL_FUNCTION macros.
Yes, I understand your suggestion on unnamed local functions and I did not mean to give the impression that I decided not to follow it. The examples I have posted so far only reflect the design decisions I indicated in the "CURRENT STATUS" section of my previous email. The open issues:
OPEN ISSUES
a) I am not sure if local functions can be nested into one another. In other words, I do not yet know if it will be possible to define a local function from within another local function.
b) I am not sure if I will provide unnamed local functions (void or not) and if so what their syntax will look like. It seems if you need this you can just use the local functions macros to program it without a dedicated syntax (but still discussing...).
c) I am not sure if I will provide local functions that execute immediately after they are defined. This might relate to b). Again, if you need this you can simply call the local function right after you define it without a dedicated syntax (but still discussing...).
are still open. As you can see, b) is unnamed local function so I will consider your suggestions (as well as other's) in detail. Ultimately, I will indicate the rational of my/our design decisions as well as other design options we discussed in the documentation so reviewers of the library will be able to see the alternatives and eventually request a changes. Note that, from an implementation prospective, unnamed local functions (with return type or void), LOCAL_BLOCK, LOCAL_EXIT, etc are trivial corollaries of the LOCAL_FUNCTION macros so my current focus really is on finalizing a solid LOCAL_FUNCTION design/implementation. Finally, thanks a lot to everyone for you comments to my last emails. I will take the time to look in details to your arguments and reply (possibly with actual working code examples). -- Lorenzo

On Wed, Sep 15, 2010 at 10:56 AM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
10) I will not merge Boost.Local with Boost.ScopeExit into a more generic Boost.Scope library. However, I will provide macros `BOOST_LOCAL_EXIT/BOOST_LOCAL_EXIT_END` which will work like Boost.ScopeExit plus they will allow to bind `this`. Boost.ScopeExit does not allow to bind `this` correct?
I have decided to allow both const and non-const binding also for the LOCAL_EXIT macros (Boost.ScopeExit instead alway binds non-const). This way the syntax of these macros is a bit more verbose than the Boost.ScopeExit macros but you can enforce constant correctness of your scope exit blocks. Also these macros can bind `this` (Boost.ScopeExit cannot). This example (somewhat long) is adapted from Boost.ScopeExit documentation (it compiles and works): // Example adapted from Boost.ScopeExit documentation. #include <contract/detail/local/exit.hpp> #include <boost/foreach.hpp> #include <boost/typeof/std/vector.hpp> // Typeof emulation mode. #include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP() // Typeof emulation mode. #include <vector> #include <ostream> #include <iostream> class world; class person { friend class world; public: typedef unsigned int id_t; typedef unsigned int evolution_t; person(): id_(0), evolution_(0) {} friend std::ostream& operator<<(std::ostream& o, person const& p) { return o << "person: " << p.id_ << ", " << p.evolution_; } private: id_t id_; evolution_t evolution_; }; BOOST_TYPEOF_REGISTER_TYPE(person) class world { public: typedef unsigned int id_t; world(): next_id_(1) {} void add_person(person const& a_person); friend std::ostream& operator<<(std::ostream& o, world const& w) { o << "world: " << w.next_id_ << ", {"; BOOST_FOREACH(person const& p, w.persons_) { o << ' ' << p << ','; } return o << "}"; } private: id_t next_id_; std::vector<person> persons_; }; BOOST_TYPEOF_REGISTER_TYPE(world) void world::add_person(person const& a_person) { persons_.push_back(a_person); // This block must be no-throw. person& p = persons_.back(); person::evolution_t checkpoint = p.evolution_; CONTRACT_DETAIL_LOCAL_EXIT( (const bind)((checkpoint)(&p)) (bind)((this)) ) { if (checkpoint == p.evolution_) this_->persons_.pop_back(); std::cout << "1st local exit" << std::endl; } CONTRACT_DETAIL_LOCAL_EXIT_END // ... checkpoint = ++p.evolution_; // Assign new id to the person. world::id_t const prev_id = p.id_; p.id_ = next_id_++; CONTRACT_DETAIL_LOCAL_EXIT( (const bind)((checkpoint)(prev_id)) (bind)((&p)(&next_id_)) ) { if (checkpoint == p.evolution_) { next_id_ = p.id_; p.id_ = prev_id; } std::cout << "2nd local exit" << std::endl; } CONTRACT_DETAIL_LOCAL_EXIT_END // ... checkpoint = ++p.evolution_; } int main() { person adamo, eva; std::cout << adamo << std::endl; std::cout << eva << std::endl; world w; w.add_person(adamo); w.add_person(eva); std::cout << w << std::endl; } I will leave it up to the library reviewers to decided if Boost.Local and Boost.ScopeExit should be merged into a single library (maybe named Boost.Scope? but then BOOST_SCOPE_FUNCTION is a worst name than BOSOT_LOCAL_FUNCTION...). -- Lorenzo
participants (9)
-
Binglong Xie
-
Dmitry Goncharov
-
Jeffrey Lee Hellrung, Jr.
-
John Bytheway
-
Lorenzo Caminiti
-
Mathias Gaunard
-
Mathieu -
-
OvermindDL1
-
Pierre Morcello