Boost.Local Review (Nov 10, 2011 to Nov 19, 2011)

Hi all, It is time! The review of Lorenzo Caminiti's proposed Boost.Local library begins tomorrow, ***November 10, 2011***, and ends on ***November 19, 2011***. Boost.Local implements local functions, local blocks, and local exits for the C++ programming language. It allows one to define a function at any declarative scope, including function scope; bind variables from the enclosing scope; and pass this function to templated STL-style algorithms. Please see the Introduction of the documentation for a longer but still brief overview. -------- The code and documentation are available from the Boost sandbox ( https://svn.boost.org/svn/boost/sandbox/): https://svn.boost.org/svn/boost/sandbox/local/ [everything] https://svn.boost.org/svn/boost/sandbox/local/boost/ [code] https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/index.html[documentation] -------- Please state clearly whether you think this library should be accepted as a Boost library. Other questions you may want to consider: - What is your evaluation of the design? - What is your evaluation of the implementation? - What is your evaluation of the documentation? - What is your evaluation of the potential usefulness of the library? - Did you try to use the library? With what compiler? Did you have any problems? - How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? - Are you knowledgeable about the problem domain? Please also consider the following issues and proposals specific to Boost.Local. Your opinion is welcome on any or all of these. - Boost.Local's local exits provide the same functionality (and then some) as Boost.ScopeExit. Does this duplication of functionality need to be dealt with, and if so, how? - Lorenzo is proposing to add boost::local::function::overload to Boost.Function as boost::function::overload. See https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost/loca... - Lorenzo is proposing to add BOOST_IDENTITY_TYPE to boost/utility. See https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN... - Likewise, Lorenzo is proposing to add BOOST_IDENTITY_VALUE to boost/utility. See https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN... -------- Lastly, please note that Boost.Local has included a copy of the Variadic Macro Data (VMD) library in boost/detail/preprocessor/variadic_macro_data. Since then, VMD has been modified and integrated into Boost.Preprocessor. After the review has concluded, Lorenzo will remove this local copy of the VMD library and replace its usage within Boost.Local with the Boost.Preprocessor variadic extensions. -------- Thanks in advance to all who participate in the review discussion; I'm looking forward to it! - Jeffrey Hellrung (Review Manager) - Gregory Crosswhite (Review Assistant)

Le 10/11/11 06:31, Jeffrey Lee Hellrung, Jr. a écrit : Hi Lorenzo, here is my review. I have not too much to say. The library is well designed and documented. Just some minor points: To be coherent with the other macros I would suggest BOOST_LOCAL_FUNCTION/BOOST_LOCAL_FUNCTION_END instead of BOOST_LOCAL_FUNCTION_PARAMS/BOOST_LOCAL_FUNCTION_NAME. Is there any possible optimization/portability improvement to add the return type to the macro for the local function? I would prefer BOOST_LOCAL_ON_SCOPE_EXIT to BOOST_LOCAL_EXIT even if longer it states clearly the intent of the block. I will not have any problem with the shorter BOOST_LOCAL_ON_SCOPE_EXIT. IIUC the local blocks intent is to protect the block from unexpected updates. Couldn't in this case all the parameters be bound as const references by default? BOOST_LOCAL_BLOCK(sum) versus BOOST_LOCAL_BLOCK(const bind& sum) What about adding CONST in the name to reinforce the intent ? BOOST_LOCAL_CONST_BLOCK(sum) I will not have any problem with the shorter BOOST_CONST_BLOCK. As variadic macros are part of the new C++11 standard I will present the sequence interface as a workaround. I have no preference between this_ and _this. Maybe it would be great to offer the possibility to the developer to name it. Can local functions have types that are typenames of the nesting function? e.g. is the following valid? template <typename T> void f() { BOOST_LOCAL_FUNCTION_PARAMS(T v) ... BOOST_LOCAL_FUNCTION_NAME(g); ... } The overload examples, let me think that you will be able to define a templated local function. I don't know which syntax could be more appropriated, but I hope you will catch the idea void f() { BOOST_LOCAL_FUNCTION(template (typename T), T v) std::cout << hex << v; BOOST_LOCAL_FUNCTION_END(print, std::string, double); // use of print with doublke or string ... } I don't have a concrete use case now, but could something like this be implemented?
--------
Please state clearly whether you think this library should be accepted as a Boost library. Yes, the library should be accepted. Other questions you may want to consider:
- What is your evaluation of the design? The interface is clean and manage with all the corner cases in an elegant way. - What is your evaluation of the implementation? I have not inspected it yet. I hope to have some time from here to the end of the review. - What is your evaluation of the documentation? Very good.
I will add a reference to the ScopedExit library when introducing Local exits and the advantages of your approach respect the one in ScopedExit. When you say " No semicolon |;| is required after the ending macro." do you mean that if a ';' is used, no error occurs, or that ';' is not allowed? Other usages of "No xxx is required" should be checked also. Could you add somewhere in the Implementation section, why the preprocessor can not parse default parameters as int y default 2 so you need a ',' between the variable and default?
- What is your evaluation of the potential usefulness of the library? Quite useful. - Did you try to use the library? With what compiler? Did you have any problems? I have compiled the examples with darwin 4.2.1, clang-2.9,3.0 with and without c++0x enabled.
I don't know why the Jamfile just build the executables and doesn't run them. Could you update the Jamfile so that we can run the examples? Some errors darwin.compile.c++ bin/darwin-4.2.1/debug/add_using_boost_lambda.o add_using_boost_lambda.cpp: In function 'int main()': add_using_boost_lambda.cpp:14: internal compiler error: in reference_to_unused, at dwarf2out.c:10603 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://developer.apple.com/bugreporter> for instructions. "g++" -ftemplate-depth-128 -O0 -fno-inline -Wall -g -dynamic -no-cpp-precomp -gdwarf-2 -fexceptions -fPIC -I"../../.." -I"/Users/viboes/boost/trunk" -c -o "bin/darwin-4.2.1/debug/add_using_boost_lambda.o" "add_using_boost_lambda.cpp" ...failed darwin.compile.c++ bin/darwin-4.2.1/debug/add_using_boost_lambda.o... ...skipped <pbin/darwin-4.2.1/debug>add_using_boost_lambda for lack of <pbin/darwin-4.2.1/debug>add_using_boost_lambda.o... ...failed updating 1 target... ...skipped 1 target... clang-darwin.compile.c++ bin/clang-darwin-3.0x/debug/add_optimizers.o add_optimizers.cpp:12:39: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS( (auto int x) (register int y) ) { ^ ../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 97 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers.cpp:12:39: error: invalid storage class specifier in function declarator add_optimizers.cpp:12:39: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS( (auto int x) (register int y) ) { ^ ../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 97 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers.cpp:12:39: error: invalid storage class specifier in function declarator 2 warnings and 2 errors generated. "/Users/viboes/clang/llvmCore-3.0-rc1.install/bin/clang++" -x c++ -std=c++0x -O0 -g -O0 -fno-inline -Wall -g -I"../../.." -I"/Users/viboes/boost/trunk" -c -o "bin/clang-darwin-3.0x/debug/add_optimizers.o" "add_optimizers.cpp" ...failed clang-darwin.compile.c++ bin/clang-darwin-3.0x/debug/add_optimizers.o... ...skipped <pbin/clang-darwin-3.0x/debug>add_optimizers for lack of <pbin/clang-darwin-3.0x/debug>add_optimizers.o... clang-darwin.compile.c++ bin/clang-darwin-3.0x/debug/add_optimizers_va.o add_optimizers_va.cpp:21:37: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS(auto int x, register int y) { ^ ../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 103 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers_va.cpp:21:37: error: invalid storage class specifier in function declarator add_optimizers_va.cpp:21:37: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS(auto int x, register int y) { ^ ../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 103 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers_va.cpp:21:37: error: invalid storage class specifier in function declarator 2 warnings and 2 errors generated. "/Users/viboes/clang/llvmCore-3.0-rc1.install/bin/clang++" -x c++ -std=c++0x -O0 -g -O0 -fno-inline -Wall -g -I"../../.." -I"/Users/viboes/boost/trunk" -c -o "bin/clang-darwin-3.0x/debug/add_optimizers_va.o" "add_optimizers_va.cpp"
- How much effort did you put into your evaluation? A glance? A quick reading? In-depth study? A quick reading of the docs and build the examples. - Are you knowledgeable about the problem domain? Yes, the domain (nested functions and scoped guards) is quite simple and well know. I have followed the evolution of the library since the beginning.
Please also consider the following issues and proposals specific to Boost.Local. Your opinion is welcome on any or all of these.
- Boost.Local's local exits provide the same functionality (and then some) as Boost.ScopeExit. Does this duplication of functionality need to be dealt with, and if so, how? I think that both libraries could be merged in a Scoped library as suggested by Lorenzo in the documentation. Once the Scoped library is released, the ScopedExit library could be set as deprecated during a certain time, before removing it definitively, as it occurred with Boost.Compose. - Lorenzo is proposing to add boost::local::function::overload to Boost.Function as boost::function::overload. See https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost/loca... An alternative could be to include it in the Functional library, together with forward and factory. - Lorenzo is proposing to add BOOST_IDENTITY_TYPE to boost/utility. See https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN... - Likewise, Lorenzo is proposing to add BOOST_IDENTITY_VALUE to boost/utility. See https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN...
I guess that both macros could be better be included in Boost.Preprocessor. Best, Vicente

Thanks for your Vicente! [I haven't had time to go through the reviews from others yet, but will be read through in short order.] On Mon, Nov 14, 2011 at 9:49 AM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 10/11/11 06:31, Jeffrey Lee Hellrung, Jr. a écrit :
[...]
void f() {
BOOST_LOCAL_FUNCTION(template (typename T), T v) std::cout << hex << v; BOOST_LOCAL_FUNCTION_END(**print, std::string, double);
// use of print with doublke or string
... }
I don't have a concrete use case now, but could something like this be implemented?
I don't think you can define templates of any kind (function or class) at function scope (...yet?). Please also consider the following issues and proposals specific to
Boost.Local. Your opinion is welcome on any or all of these.
- Boost.Local's local exits provide the same functionality (and then some) as Boost.ScopeExit. Does this duplication of functionality need to be dealt with, and if so, how?
I think that both libraries could be merged in a Scoped library as suggested by Lorenzo in the documentation. Once the Scoped library is released, the ScopedExit library could be set as deprecated during a certain time, before removing it definitively, as it occurred with Boost.Compose.
I think Boost.Scope or Boost.Scoped wouldn't be bad names for a merged library (the current name Boost.Local I think is also fine). - Lorenzo is proposing to add boost::local::function::**overload to
Boost.Function as boost::function::overload. See https://svn.boost.org/svn/**boost/sandbox/local/libs/** local/doc/html/boost/local/**function/overload.html<https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost/local/function/overload.html>
An alternative could be to include it in the Functional library, together with forward and factory.
I'm currently thinking that unless there's a positive push to move boost::local::function::overload out of Boost.Local, it will remain in Boost.Local.
- Lorenzo is proposing to add BOOST_IDENTITY_TYPE to boost/utility. See
https://svn.boost.org/svn/**boost/sandbox/local/libs/** local/doc/html/BOOST_IDENTITY_**TYPE.html<https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDENTITY_TYPE.html> - Likewise, Lorenzo is proposing to add BOOST_IDENTITY_VALUE to boost/utility. See https://svn.boost.org/svn/**boost/sandbox/local/libs/** local/doc/html/BOOST_IDENTITY_**VALUE.html<https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDENTITY_VALUE.html>
I guess that both macros could be better be included in Boost.Preprocessor.
Except that both IDENTITY_TYPE and IDENTITY_VALUE are intimately related to C++ types and C++ expressions; and, AFAIK, the Boost.Preprocessor library has no facilities meant to directly address either, i.e., it operates purely in "preprocessor space". I would think the aforementioned macros are more like BOOST_STATIC_CONSTANT than anything in Boost.Preprocessor. - Jeff

Le 14/11/11 19:15, Jeffrey Lee Hellrung, Jr. a écrit :
On Mon, Nov 14, 2011 at 9:49 AM, Vicente J. Botet Escriba< vicente.botet@wanadoo.fr> wrote:
Le 10/11/11 06:31, Jeffrey Lee Hellrung, Jr. a écrit :
[...]
void f() {
BOOST_LOCAL_FUNCTION(template (typename T), T v) std::cout<< hex<< v; BOOST_LOCAL_FUNCTION_END(**print, std::string, double);
// use of print with doublke or string
... }
I don't have a concrete use case now, but could something like this be implemented?
I don't think you can define templates of any kind (function or class) at function scope (...yet?). Oups, my bad :(
Please also consider the following issues and proposals specific to
Boost.Local. Your opinion is welcome on any or all of these.
- Boost.Local's local exits provide the same functionality (and then some) as Boost.ScopeExit. Does this duplication of functionality need to be dealt with, and if so, how?
I think that both libraries could be merged in a Scoped library as suggested by Lorenzo in the documentation. Once the Scoped library is released, the ScopedExit library could be set as deprecated during a certain time, before removing it definitively, as it occurred with Boost.Compose.
I think Boost.Scope or Boost.Scoped wouldn't be bad names for a merged library (the current name Boost.Local I think is also fine). I don't know if in English Locale and Local sound enough different, but for me there is no big difference. I will prefer a distinct name.
- Lorenzo is proposing to add boost::local::function::**overload to
Boost.Function as boost::function::overload. See https://svn.boost.org/svn/**boost/sandbox/local/libs/** local/doc/html/boost/local/**function/overload.html<https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost/local/function/overload.html>
An alternative could be to include it in the Functional library, together with forward and factory.
I'm currently thinking that unless there's a positive push to move boost::local::function::overload out of Boost.Local, it will remain in Boost.Local.
I have no problem. It was just an idea.
- Lorenzo is proposing to add BOOST_IDENTITY_TYPE to boost/utility. See
https://svn.boost.org/svn/**boost/sandbox/local/libs/** local/doc/html/BOOST_IDENTITY_**TYPE.html<https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDENTITY_TYPE.html> - Likewise, Lorenzo is proposing to add BOOST_IDENTITY_VALUE to boost/utility. See https://svn.boost.org/svn/**boost/sandbox/local/libs/** local/doc/html/BOOST_IDENTITY_**VALUE.html<https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDENTITY_VALUE.html>
I guess that both macros could be better be included in Boost.Preprocessor.
Except that both IDENTITY_TYPE and IDENTITY_VALUE are intimately related to C++ types and C++ expressions; and, AFAIK, the Boost.Preprocessor library has no facilities meant to directly address either, i.e., it operates purely in "preprocessor space". I would think the aforementioned macros are more like BOOST_STATIC_CONSTANT than anything in Boost.Preprocessor. You are right, even if the main goal is purely to solve a preprocessor issue, the solution goes behind the scope of Boost.Preprocessor.
Best, Vicente

On Mon, Nov 14, 2011 at 1:26 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 14/11/11 19:15, Jeffrey Lee Hellrung, Jr. a écrit :
I think Boost.Scope or Boost.Scoped wouldn't be bad names for a merged library (the current name Boost.Local I think is also fine).
I don't know if in English Locale and Local sound enough different, but for me there is no big difference. I will prefer a distinct name.
Well, they certainly *sound* different (they accent different syllables), but the closeness in spelling is certainly a consideration. AFAIK, no one else has brought up this issue yet (except gmail's autocomplete). - Jeff

On 14 November 2011 15:32, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
On Mon, Nov 14, 2011 at 1:26 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 14/11/11 19:15, Jeffrey Lee Hellrung, Jr. a écrit :
I think Boost.Scope or Boost.Scoped wouldn't be bad names for a merged library (the current name Boost.Local I think is also fine).
I don't know if in English Locale and Local sound enough different, but for me there is no big difference. I will prefer a distinct name.
Well, they certainly *sound* different (they accent different syllables), but the closeness in spelling is certainly a consideration.
AFAIK, no one else has brought up this issue yet (except gmail's autocomplete).
Boost.Local is the only library this far in Boost that I have to silently pronounce in my head before I realize that it's not Boost.Locale. Since the two libraries for a while was active on the mailing list at the same time, it did cause me some confusion in the beginning. I'm very easily confused, however, so quite possible I'm the only one seeing this as a problem :) That said, it's absolutely no big deal, but I think it would be better if the names were not so closely named.. - christian

On Mon, Nov 14, 2011 at 3:06 PM, Christian Holmquist <c.holmquist@gmail.com>wrote:
On 14 November 2011 15:32, Jeffrey Lee Hellrung, Jr. < jeffrey.hellrung@gmail.com> wrote:
On Mon, Nov 14, 2011 at 1:26 PM, Vicente J. Botet Escriba < vicente.botet@wanadoo.fr> wrote:
Le 14/11/11 19:15, Jeffrey Lee Hellrung, Jr. a écrit :
I think Boost.Scope or Boost.Scoped wouldn't be bad names for a merged library (the current name Boost.Local I think is also fine).
I don't know if in English Locale and Local sound enough different, but for me there is no big difference. I will prefer a distinct name.
Well, they certainly *sound* different (they accent different syllables), but the closeness in spelling is certainly a consideration.
AFAIK, no one else has brought up this issue yet (except gmail's autocomplete).
Boost.Local is the only library this far in Boost that I have to silently pronounce in my head before I realize that it's not Boost.Locale.
Since the two libraries for a while was active on the mailing list at the same time, it did cause me some confusion in the beginning. I'm very easily confused, however, so quite possible I'm the only one seeing this as a problem :)
That said, it's absolutely no big deal, but I think it would be better if the names were not so closely named..
Do you have any preferred alternative name to Local? (or, I guess, Locale...but almost surely too late to change that!) - Jeff

Boost.Local is the only library this far in Boost that I have to silently pronounce in my head before I realize that it's not Boost.Locale.
Since the two libraries for a while was active on the mailing list at the same time, it did cause me some confusion in the beginning. I'm very easily confused, however, so quite possible I'm the only one seeing this as a problem :)
That said, it's absolutely no big deal, but I think it would be better if the names were not so closely named..
Do you have any preferred alternative name to Local? (or, I guess, Locale...but almost surely too late to change that!)
Boost.LocalFunction? - Christian

On Mon, Nov 14, 2011 at 6:52 PM, Christian Holmquist <c.holmquist@gmail.com> wrote:
Boost.Local is the only library this far in Boost that I have to silently pronounce in my head before I realize that it's not Boost.Locale.
Since the two libraries for a while was active on the mailing list at the same time, it did cause me some confusion in the beginning. I'm very easily confused, however, so quite possible I'm the only one seeing this as a problem :)
That said, it's absolutely no big deal, but I think it would be better if the names were not so closely named..
Do you have any preferred alternative name to Local? (or, I guess, Locale...but almost surely too late to change that!)
Boost.LocalFunction?
Well... no because Boost.Local is not just about local functions. I also has local blocks and local exits so LocalFunction will not cover the entire domain of Boost.Local and it will make the names of the macros for local exits BOOST_LOCAL_FUNCTION_EXIT and local blocks BOOST_LOCAL_FUNCTION_BLOCK misleading. Key points to keep in mind when searching for the name are: 1) I'm not a native English speaker so distrust my opinion ;) 2) In CS local functions are know as either local functions (C++ uses similar terms like local classes (not nested classes), local variables, etc) or nested functions (used by wiki, GCC, etc): http://en.wikipedia.org/wiki/Nested_function#An_example http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html 3) Should this library be merged with Boost.ScopeExit? If so, this library name might or not need to overlap with existing ScopeExit macros.* Alternatives I could think of are: a) Boost.Local: BOOST_LOCAL_FUNCTION (current), BOOST_LOCAL_EXIT, BOOST_LOCAL_BLOCK b1) Boost.Nested: BOOST_NESTED_FUNCTION (as named by GCC), BOOST_NESTED_EXIT (does this make sense?), BOOST_NESTED_BLOCK b2) Boost.Nested: BOOST_NESTED_FUNCTION, BOOST_NESTED_SCOPE_EXIT (does this make more sense? is it too long?), BOOST_NESTED_BLOCK c) Boost.Scoped: BOOST_SCOPED_FUNCTION (does this make sense?), BOOST_SCOPED_EXIT (too similar to existing BOOT_SCOPE_EXIT?), BOOST_SCOPED_BLOCK d) Boost.Scope: BOOST_SCOPE_FUNCTION (does this make sense?), BOOST_SCOPE_EXIT (same as existing name but different API), BOOST_SCOPE_BLOCK I'd say either a) or b2) because they give the most descriptive names to the function, exit, and block macros. All, which one you do you prefer? (*) Here's what I propose in a footnote of the Tutorial section: [17] Rationale. This library could be merged together with Boost.ScopeExit into a new library named Boost.Scope (from the meaning of the word "scope" in computer programming). This would be justified by the fact that BOOST_LOCAL_EXIT simply extends the functionality already provided by BOOST_SCOPE_EXIT. The headers will be "boost/scope/function.hpp", "boost/scope/block.hpp", and "boost/scope/exit.hpp" (for backward compatibility with Boost.ScopeExit, the header "boost/scope_exit.hpp" could also be kept and it would be equivalent to including "boost/scope/exit.hpp"). However, the new BOOST_SCOPE_EXIT macro will not be backward compatible with the current Boost.ScopeExit macro because it will require to prefix the bound variable with bind or const bind (in order to differentiate from constant and non-constant binding and to prevent the bound tokens from ever starting with a non-alphanumeric symbol like &). Local blocks would be named "scope blocks" and they would be provided by the BOOST_SCOPE_BLOCK... macros (the "scope block" name seems reasonably expressive). However, local functions would have to be named "scope functions" and they would be provided by the BOOST_SCOPE_FUNCTION... macros. This name might not be expressive enough because local functions are not known under the name of "scope functions" -- they are indeed known by either the name of "local functions" or by the name of "nested functions" (GCC compiler extension). Thanks. --Lorenzo

On Mon, Nov 14, 2011 at 7:31 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Nov 14, 2011 at 6:52 PM, Christian Holmquist <c.holmquist@gmail.com> wrote:
Boost.Local is the only library this far in Boost that I have to silently pronounce in my head before I realize that it's not Boost.Locale.
Since the two libraries for a while was active on the mailing list at the same time, it did cause me some confusion in the beginning. I'm very easily confused, however, so quite possible I'm the only one seeing this as a problem :)
That said, it's absolutely no big deal, but I think it would be better if the names were not so closely named..
Do you have any preferred alternative name to Local? (or, I guess, Locale...but almost surely too late to change that!)
Boost.LocalFunction?
Well... no because Boost.Local is not just about local functions. I also has local blocks and local exits so LocalFunction will not cover the entire domain of Boost.Local and it will make the names of the macros for local exits BOOST_LOCAL_FUNCTION_EXIT and local blocks BOOST_LOCAL_FUNCTION_BLOCK misleading.
Key points to keep in mind when searching for the name are: 1) I'm not a native English speaker so distrust my opinion ;) 2) In CS local functions are know as either local functions (C++ uses similar terms like local classes (not nested classes), local
I forgot a reference for the local function name. Here it is (it's N2511): http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2511.html
variables, etc) or nested functions (used by wiki, GCC, etc): http://en.wikipedia.org/wiki/Nested_function#An_example http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html 3) Should this library be merged with Boost.ScopeExit? If so, this library name might or not need to overlap with existing ScopeExit macros.*
Alternatives I could think of are: a) Boost.Local: BOOST_LOCAL_FUNCTION (current), BOOST_LOCAL_EXIT, BOOST_LOCAL_BLOCK b1) Boost.Nested: BOOST_NESTED_FUNCTION (as named by GCC), BOOST_NESTED_EXIT (does this make sense?), BOOST_NESTED_BLOCK b2) Boost.Nested: BOOST_NESTED_FUNCTION, BOOST_NESTED_SCOPE_EXIT (does this make more sense? is it too long?), BOOST_NESTED_BLOCK c) Boost.Scoped: BOOST_SCOPED_FUNCTION (does this make sense?), BOOST_SCOPED_EXIT (too similar to existing BOOT_SCOPE_EXIT?), BOOST_SCOPED_BLOCK d) Boost.Scope: BOOST_SCOPE_FUNCTION (does this make sense?), BOOST_SCOPE_EXIT (same as existing name but different API), BOOST_SCOPE_BLOCK
I'd say either a) or b2) because they give the most descriptive names to the function, exit, and block macros. All, which one you do you prefer?
(*) Here's what I propose in a footnote of the Tutorial section: [17] Rationale. This library could be merged together with Boost.ScopeExit into a new library named Boost.Scope (from the meaning of the word "scope" in computer programming). This would be justified by the fact that BOOST_LOCAL_EXIT simply extends the functionality already provided by BOOST_SCOPE_EXIT. The headers will be "boost/scope/function.hpp", "boost/scope/block.hpp", and "boost/scope/exit.hpp" (for backward compatibility with Boost.ScopeExit, the header "boost/scope_exit.hpp" could also be kept and it would be equivalent to including "boost/scope/exit.hpp"). However, the new BOOST_SCOPE_EXIT macro will not be backward compatible with the current Boost.ScopeExit macro because it will require to prefix the bound variable with bind or const bind (in order to differentiate from constant and non-constant binding and to prevent the bound tokens from ever starting with a non-alphanumeric symbol like &). Local blocks would be named "scope blocks" and they would be provided by the BOOST_SCOPE_BLOCK... macros (the "scope block" name seems reasonably expressive). However, local functions would have to be named "scope functions" and they would be provided by the BOOST_SCOPE_FUNCTION... macros. This name might not be expressive enough because local functions are not known under the name of "scope functions" -- they are indeed known by either the name of "local functions" or by the name of "nested functions" (GCC compiler extension).
--Lorenzo

On Mon, Nov 14, 2011 at 7:35 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Nov 14, 2011 at 7:31 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Nov 14, 2011 at 6:52 PM, Christian Holmquist <c.holmquist@gmail.com> wrote:
Boost.Local is the only library this far in Boost that I have to silently pronounce in my head before I realize that it's not Boost.Locale.
Key points to keep in mind when searching for the name are: 1) I'm not a native English speaker so distrust my opinion ;) 2) In CS local functions are know as either local functions (C++ uses similar terms like local classes (not nested classes), local
I forgot a reference for the local function name. Here it is (it's N2511): http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2511.html
variables, etc) or nested functions (used by wiki, GCC, etc): http://en.wikipedia.org/wiki/Nested_function#An_example http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html 3) Should this library be merged with Boost.ScopeExit? If so, this library name might or not need to overlap with existing ScopeExit macros.*
Alternatives I could think of are: a) Boost.Local: BOOST_LOCAL_FUNCTION (current), BOOST_LOCAL_EXIT, BOOST_LOCAL_BLOCK b1) Boost.Nested: BOOST_NESTED_FUNCTION (as named by GCC), BOOST_NESTED_EXIT (does this make sense?), BOOST_NESTED_BLOCK b2) Boost.Nested: BOOST_NESTED_FUNCTION, BOOST_NESTED_SCOPE_EXIT (does this make more sense? is it too long?), BOOST_NESTED_BLOCK c) Boost.Scoped: BOOST_SCOPED_FUNCTION (does this make sense?), BOOST_SCOPED_EXIT (too similar to existing BOOT_SCOPE_EXIT?), BOOST_SCOPED_BLOCK d) Boost.Scope: BOOST_SCOPE_FUNCTION (does this make sense?), BOOST_SCOPE_EXIT (same as existing name but different API), BOOST_SCOPE_BLOCK
Andrzej proposed to also consider CLOSURE instead of FUNCTION name: http://en.wikipedia.org/wiki/Closure_%28computer_science%29 If we use CLOSURE instead of FUNCTION, the alternatives become: a) Boost.Local: BOOST_LOCAL_CLOSURE[_END], BOOST_LOCAL_EXIT[_END], BOOST_LOCAL_BLOCK[_END] b1) Boost.Nested: BOOST_NESTED_CLOSURE[_END], BOOST_NESTED_EXIT[_END], BOOST_NESTED_BLOCK[_END] b2) Boost.Nested: BOOST_NESTED_CLOSURE[_END], BOOST_NESTED_SCOPE_EXIT[_END], BOOST_NESTED_BLOCK[_END] c) Boost.Scoped: BOOST_SCOPED_CLOSURE[_END], BOOST_SCOPED_EXIT[_END], BOOST_SCOPED_BLOCK[_END] d) Boost.Scope: BOOST_SCOPE_CLOSURE[_END], BOOST_SCOPE_EXIT[_END], BOOST_SCOPE_BLOCK[_END] Do you have any preference? FUNCTION or CLOSURE? And also a), b1), b2), c) or d)? (Or something else...)
I'd say either a) or b2) because they give the most descriptive names to the function, exit, and block macros. All, which one you do you prefer?
(*) Here's what I propose in a footnote of the Tutorial section: [17] Rationale. This library could be merged together with Boost.ScopeExit into a new library named Boost.Scope (from the meaning of the word "scope" in computer programming). This would be justified by the fact that BOOST_LOCAL_EXIT simply extends the functionality already provided by BOOST_SCOPE_EXIT. The headers will be "boost/scope/function.hpp", "boost/scope/block.hpp", and "boost/scope/exit.hpp" (for backward compatibility with Boost.ScopeExit, the header "boost/scope_exit.hpp" could also be kept and it would be equivalent to including "boost/scope/exit.hpp"). However, the new BOOST_SCOPE_EXIT macro will not be backward compatible with the current Boost.ScopeExit macro because it will require to prefix the bound variable with bind or const bind (in order to differentiate from constant and non-constant binding and to prevent the bound tokens from ever starting with a non-alphanumeric symbol like &). Local blocks would be named "scope blocks" and they would be provided by the BOOST_SCOPE_BLOCK... macros (the "scope block" name seems reasonably expressive). However, local functions would have to be named "scope functions" and they would be provided by the BOOST_SCOPE_FUNCTION... macros. This name might not be expressive enough because local functions are not known under the name of "scope functions" -- they are indeed known by either the name of "local functions" or by the name of "nested functions" (GCC compiler extension).
Thanks. --Lorenzo

My votes for names: this_ BOOST_LOCAL_FUNCTION BOOST_LOCAL_FUNCTION_END Regards, Kris

Jeffrey Lee Hellrung, Jr. wrote:
Do you have any preferred alternative name to Local? (or, I guess, Locale...but almost surely too late to change that!)
How about Boost.Localization? The name Boost.Locale was probably invented by a non-native speaker. This is no coincidence, because a native speaker would have had little incentive (and lack of real world experience) to develop a localization library. This doesn't mean that Boost.Locale is a bad name. An advantage of Boost.Locale over Boost.Localization is that nobody will assume that he knows the scope of the library without looking at its documentation first. Given the broad scope of that library, any clear and unambiguous name would suggest a too narrow scope. The situation is different for Boost.Local, which has a sufficiently narrow scope to allow for a fitting name. The names Boost.ScopedExit and Boost.Local both seem to fit quite well for their respective libraries. The names Boost.Scope or Boost.Scoped for a merged library don't convince me. Perhaps Boost.Block would be OK, but Boost.Local sounds nicer to me. Regards, Thomas

On Mon, Nov 14, 2011 at 12:49 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 10/11/11 06:31, Jeffrey Lee Hellrung, Jr. a écrit :
Hi Lorenzo, here is my review.
Hi Vicente, thanks for your review!
I have not too much to say. The library is well designed and documented.
:)
Just some minor points:
To be coherent with the other macros I would suggest BOOST_LOCAL_FUNCTION/BOOST_LOCAL_FUNCTION_END instead of BOOST_LOCAL_FUNCTION_PARAMS/BOOST_LOCAL_FUNCTION_NAME.
I have been considering this too because sometimes I get confused and write BOOST_LOCAL_FUNCTION without the _PARAMS. The BOOST_LOCAL_FUNCTION and BOOST_LOCAL_FUNTION_END names are also more consistent with the early experimentation on local functions done by Alexander Nasonov and Steven Watanabe http://thread.gmane.org/gmane.comp.lib.boost.devel/168612. OTOH, I do think that _PARAMS and _NAME are more descriptive names because they clearly say what you specify using these macros and that is why I ultimately decided to go with the more descriptive names. I have not strong feelings between these different names and I will haply comply with the consensus reached during this review. Does anyone else have an opinion?
Is there any possible optimization/portability improvement to add the return type to the macro for the local function?
The _only_ benefit in passing the result type within the macros is that when you also specify the types of all bound variables the library will not use Boost.Typeof. In other words, right now even if you specify the types of all bound variables `[const] bind(type)[&] var`, the library still has to use typeof to deduce the result type because such a type is not directly passed to the macros. I consider this a _very_ minor advantage largely outweighed by the better syntax achieved by moving the result type outside the macro. This is somewhat stated in the docs by the 3rd sentence of this subsection: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
I would prefer BOOST_LOCAL_ON_SCOPE_EXIT to BOOST_LOCAL_EXIT even if longer it states clearly the intent of the block. I will not have any problem with the shorter BOOST_LOCAL_ON_SCOPE_EXIT.
I don't like BOOST_LOCAL_ON_SCOPE_EXIT because it's too long. How about BOOST_SCOPED_EXIT, BOOST_SCOPED_BLOCK, BOOST_SCOPED_FUNCTION, etc? The library will then be named Boost.Scoped and merged with ScopeExit... if the merge is agreed on during this review.
IIUC the local blocks intent is to protect the block from unexpected updates. Couldn't in this case all the parameters be bound as const references by default?
BOOST_LOCAL_BLOCK(sum) versus BOOST_LOCAL_BLOCK(const bind& sum)
What about adding CONST in the name to reinforce the intent ? BOOST_LOCAL_CONST_BLOCK(sum)
I will not have any problem with the shorter BOOST_CONST_BLOCK.
Not quite because you might want to modify one variable but make sure that another one remains const. Therefore, I think it is best to leave full control to the user that can specify which variable to be bound by const and which not. For example: int x = 10; int y = -10; BOOST_LOCAL_BLOCK(const bind& x, bind& y) { // semantics: this block of code does not change x but it changes y assert(x >= 0); y = x + 10; } BOOST_LOCAL_BLOCK_END Also I think it's easier for the user if LOCAL_BLOCK has the same binding interface of LOCAL_EXIT and LOCAL_FUNCTION_PARAMS (so no implied const, etc).
As variadic macros are part of the new C++11 standard I will present the sequence interface as a workaround.
That could be done... I do think that Boost.Local is most useful with C++03 because with C++11 you can use lambdas. However, even with C++03 most (all?) compilers support variadics so the sequencing syntax could indeed be presented as a "workaround" to apply when you want to be 100% compliant with C++03 pp. That said, do you think it is heavy that the docs present all examples in both syntaxes? If not, then I'd leave it as is.
I have no preference between this_ and _this. Maybe it would be great to offer the possibility to the developer to name it.
You already can by #defining the configuration macro BOOST_LOCAL_CONFIG_THIS_PARAM_NAME: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_LOCA... As it was suggested, I'm thinking that I will change from this_ to _this (to be consistent with Phoenix) and require to use _this in both the local function declaration and implementation (and error at compile-time if you use this instead of _this in the declaration but I still can't error if you mistakenly use this instead of _this in the definition :( ). I will also leave the config macro so the users can change this name if they want/need to.
Can local functions have types that are typenames of the nesting function? e.g. is the following valid?
template <typename T> void f() {
BOOST_LOCAL_FUNCTION_PARAMS(T v) ... BOOST_LOCAL_FUNCTION_NAME(g);
... }
Yes, this is possible but you need to use the version of the macros with the _TPL postfix: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
The overload examples, let me think that you will be able to define a templated local function. I don't know which syntax could be more appropriated, but I hope you will catch the idea
void f() {
BOOST_LOCAL_FUNCTION(template (typename T), T v) std::cout << hex << v; BOOST_LOCAL_FUNCTION_END(print, std::string, double);
// use of print with doublke or string
... }
I don't have a concrete use case now, but could something like this be implemented?
No :( because local classes and functions cannot have their own template parameters in C++ :( (not even in C++11) they can only use template parameters they see from the enclosing scope. (BTW, the discussion on the limitation that local functions cannot be templates incidentally led to introduce overload<> but overloading local function and local function templates remain different things.)
--------
Please state clearly whether you think this library should be accepted as a Boost library.
Yes, the library should be accepted.
:)
Other questions you may want to consider:
- What is your evaluation of the design?
The interface is clean and manage with all the corner cases in an elegant way.
- What is your evaluation of the implementation?
I have not inspected it yet. I hope to have some time from here to the end of the review.
While looking at the implementation, also look at: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
- What is your evaluation of the documentation?
Very good.
I will add a reference to the ScopedExit library when introducing Local exits and the advantages of your approach respect the one in ScopedExit.
When you say " No semicolon |;| is required after the ending macro." do you mean that if a ';' is used, no error occurs, or that ';' is not allowed? Other usages of "No xxx is required" should be checked also.
It just means that ; is not required. You can still put ; there, it will work (I just triple checked :) ), but it is not required. That's true all over (otherwise I say "it's required not to put it there").
Could you add somewhere in the Implementation section, why the preprocessor can not parse default parameters as int y default 2 so you need a ',' between the variable and default?
There is already a footnote explaining the rationale of why = cannot be used for default parameter values: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca... I can expand this text indicating why default requires a preceding comma. The comma is needed because the tokens `int x` can be anything `mytype myvar` so the pp has no way to remove them to separate the default value from the rest of the parameter declaration. The default values need to be separated (stripped) because they are not part of the function type and the library needs to build the function type for some internal template metaprogramming manipulations. Also I need to count the number of default parameter to select which functor to use to declare the local function so it will have the call operator() for each default parameter (the count is done by the pp and it requires to identify which parameter has a default so it needs to be separated by the rest of the parameter declaration-- the count cannot be done using MPL because again default parameter value are not part of the function type so I can't use template metaprogramming to inspect them, I need to use pp metaprogramming). I know, this is quite a long story...
- What is your evaluation of the potential usefulness of the library?
Quite useful.
- Did you try to use the library? With what compiler? Did you have any problems?
I have compiled the examples with darwin 4.2.1, clang-2.9,3.0 with and without c++0x enabled.
Cool. I've only tested with: GNU Compiler Collection (GCC) 4.5.1 (with and without C++11 features enabled) on Ubuntu Linux 10. GCC 4.3.4 on Cygwin. Miscrosoft Visual Studio Compiler (MSVC) 8.0 on Windows XP. If the library is accepted a larger set of compilers will be supported (if a compiler can handle Boost.Typeof and Boost.ScopeExit, there's no reason that I can see why it should not be able to handle Boost.Local).
I don't know why the Jamfile just build the executables and doesn't run them. Could you update the Jamfile so that we can run the examples?
Yes. I will also have to add tests to the library for now I only have examples.
Some errors
I looked at the errors below, they are not in Boost.Local: 1) One error is because Boost.Lambda generates an internal error in Darwing (add_using_boost_lambda.cpp has no Boost.Local code). I don't know why... 2) All other errors are because the add_optimizers.cpp intentionally uses the auto classifier to show that Boost.Local works with auto and register parameters. However, auto is deprecated so you get all the other errors below.
darwin.compile.c++ bin/darwin-4.2.1/debug/add_using_boost_lambda.o add_using_boost_lambda.cpp: In function 'int main()': add_using_boost_lambda.cpp:14: internal compiler error: in
Actually, this example only uses Boost.Lambda... no Boost.Local.
reference_to_unused, at dwarf2out.c:10603 Please submit a full bug report, with preprocessed source if appropriate. See <URL:http://developer.apple.com/bugreporter> for instructions.
"g++" -ftemplate-depth-128 -O0 -fno-inline -Wall -g -dynamic -no-cpp-precomp -gdwarf-2 -fexceptions -fPIC -I"../../.." -I"/Users/viboes/boost/trunk" -c -o "bin/darwin-4.2.1/debug/add_using_boost_lambda.o" "add_using_boost_lambda.cpp"
...failed darwin.compile.c++ bin/darwin-4.2.1/debug/add_using_boost_lambda.o... ...skipped <pbin/darwin-4.2.1/debug>add_using_boost_lambda for lack of <pbin/darwin-4.2.1/debug>add_using_boost_lambda.o... ...failed updating 1 target... ...skipped 1 target...
clang-darwin.compile.c++ bin/clang-darwin-3.0x/debug/add_optimizers.o add_optimizers.cpp:12:39: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS( (auto int x) (register int y) ) {
This is because this example uses the auto classifier which is deprecated in C++ so the compiler signals that. The purpose of this example is to the show that Boost.Local supports auto and register classifiers even if they are deprecated-- so just don't compile this example with compilers that error on auto/register. I'll put some #if guard in the example.
../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 97 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers.cpp:12:39: error: invalid storage class specifier in function declarator add_optimizers.cpp:12:39: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS( (auto int x) (register int y) ) { ^ ../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 97 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers.cpp:12:39: error: invalid storage class specifier in function declarator 2 warnings and 2 errors generated.
All above is because of the deprecated auto classifier.
"/Users/viboes/clang/llvmCore-3.0-rc1.install/bin/clang++" -x c++ -std=c++0x -O0 -g -O0 -fno-inline -Wall -g -I"../../.." -I"/Users/viboes/boost/trunk" -c -o "bin/clang-darwin-3.0x/debug/add_optimizers.o" "add_optimizers.cpp"
...failed clang-darwin.compile.c++ bin/clang-darwin-3.0x/debug/add_optimizers.o... ...skipped <pbin/clang-darwin-3.0x/debug>add_optimizers for lack of <pbin/clang-darwin-3.0x/debug>add_optimizers.o... clang-darwin.compile.c++ bin/clang-darwin-3.0x/debug/add_optimizers_va.o add_optimizers_va.cpp:21:37: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS(auto int x, register int y) { ^ ../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 103 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers_va.cpp:21:37: error: invalid storage class specifier in function declarator add_optimizers_va.cpp:21:37: warning: 'auto' storage class specifier is not permitted in C++11, and will not be supported in future releases int BOOST_LOCAL_FUNCTION_PARAMS(auto int x, register int y) { ^ ../../../boost/local/function.hpp:167:65: note: expanded from: BOOST_LOCAL_FUNCTION_PARAMS_(__LINE__, 0 /* no template */, __VA_ARGS__) ^ ../../../boost/local/function.hpp:163:41: note: expanded from: (void) /* for empty seq */, __VA_ARGS__), \ ^ ../../../boost/local/aux_/preprocessor/variadic/to_seq.hpp:39:7: note: expanded from: )(__VA_ARGS__) ^ note: (skipping 103 expansions in backtrace; use -fmacro-backtrace-limit=0 to see all) /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:18:60: note: expanded from: # define BOOST_PP_IIF(bit, t, f) BOOST_PP_IIF_I(bit, t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:25:63: note: expanded from: # define BOOST_PP_IIF_I(bit, t, f) BOOST_PP_IIF_ ## bit(t, f) ^ /Users/viboes/boost/trunk/boost/preprocessor/control/iif.hpp:31:31: note: expanded from: # define BOOST_PP_IIF_0(t, f) f ^ add_optimizers_va.cpp:21:37: error: invalid storage class specifier in function declarator 2 warnings and 2 errors generated.
"/Users/viboes/clang/llvmCore-3.0-rc1.install/bin/clang++" -x c++ -std=c++0x -O0 -g -O0 -fno-inline -Wall -g -I"../../.." -I"/Users/viboes/boost/trunk" -c -o "bin/clang-darwin-3.0x/debug/add_optimizers_va.o" "add_optimizers_va.cpp"
Same story, the deprecated auto classifier.
- How much effort did you put into your evaluation? A glance? A quick reading? In-depth study?
A quick reading of the docs and build the examples.
- Are you knowledgeable about the problem domain?
Yes, the domain (nested functions and scoped guards) is quite simple and well know. I have followed the evolution of the library since the beginning.
Please also consider the following issues and proposals specific to Boost.Local. Your opinion is welcome on any or all of these.
- Boost.Local's local exits provide the same functionality (and then some) as Boost.ScopeExit. Does this duplication of functionality need to be dealt with, and if so, how?
I think that both libraries could be merged in a Scoped library as suggested by Lorenzo in the documentation. Once the Scoped library is released, the ScopedExit library could be set as deprecated during a certain time, before removing it definitively, as it occurred with Boost.Compose.
- Lorenzo is proposing to add boost::local::function::overload to Boost.Function as boost::function::overload. See
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost/loca...
An alternative could be to include it in the Functional library, together with forward and factory.
- Lorenzo is proposing to add BOOST_IDENTITY_TYPE to boost/utility. See
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN... - Likewise, Lorenzo is proposing to add BOOST_IDENTITY_VALUE to boost/utility. See
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN...
I guess that both macros could be better be included in Boost.Preprocessor.
IMO, it shouldn't go in Boost.Preprocessor because it is about C++ types and not the pp (which is actually C). BTW, these macros are really trivial, they don't use variadics at all, and I find IDENTITY_TYPE very handy: #define BOOST_IDENTITY_TYPE(parenthesized_type) \ boost::function_traits< void parenthesized_type >::arg1_type namespace boost { namespace aux { template<typename T> inline typename boost::add_reference<T>::type identity_value( typename boost::add_reference<T>::type value) { return value; } }} // namespace boost::aux #define BOOST_IDENTITY_VALUE(parenthesized_value) \ boost::aux::identity_value parenthesized_value BOOST_IDENTITY_TYPE((boost::mpl::vector<char, int>)) BOOST_IDENTITY_VALUE((boost::mpl::vector<char, int>::value)) Thanks a lot for your review! --Lorenzo

On Mon, Nov 14, 2011 at 4:00 PM, Lorenzo Caminiti <lorcaminiti@gmail.com>wrote: [...]
As it was suggested, I'm thinking that I will change from this_ to _this (to be consistent with Phoenix) and require to use _this in both the local function declaration and implementation (and error at compile-time if you use this instead of _this in the declaration but I still can't error if you mistakenly use this instead of _this in the definition :( ). I will also leave the config macro so the users can change this name if they want/need to.
[...] I think it would be more consistent with other Boost libraries to use "this_" rather than "_this". A leading underscore is used to distinguish domain-defined keywords and placeholders. This *kind of* fits that, but...well, to me, not exactly. On the other hand, one would almost certainly prefer to just use "this", except...you can't. Anytime you want to use a C++ keyword as an identifier but can't actually use the keyword verbatim, the consistent practice has been to append an underscore. Just my opinion, and it's not a big deal either way, - Jeff

On Mon, Nov 14, 2011 at 7:25 PM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> wrote:
On Mon, Nov 14, 2011 at 4:00 PM, Lorenzo Caminiti <lorcaminiti@gmail.com>wrote: [...]
As it was suggested, I'm thinking that I will change from this_ to _this (to be consistent with Phoenix) and require to use _this in both the local function declaration and implementation (and error at compile-time if you use this instead of _this in the declaration but I still can't error if you mistakenly use this instead of _this in the definition :( ). I will also leave the config macro so the users can change this name if they want/need to.
[...]
I think it would be more consistent with other Boost libraries to use "this_" rather than "_this".
A leading underscore is used to distinguish domain-defined keywords and placeholders. This *kind of* fits that, but...well, to me, not exactly.
On the other hand, one would almost certainly prefer to just use "this", except...you can't. Anytime you want to use a C++ keyword as an identifier
Yes, I can't :( This is marked in the Tutorial as Warning. The only way I could figure out it's illegal because it relies on an undefined behavior of static_cast (see Tutorial section footnote #13): http://groups.google.com/group/comp.lang.c++.moderated/browse_thread/thread/...
but can't actually use the keyword verbatim, the consistent practice has been to append an underscore.
Just my opinion, and it's not a big deal either way,
In this email thread: http://lists.boost.org/Archives/boost/2011/04/179834.php Three things where pointed out: 1) _ prefix is for placeholders. 2) _ postfix is for keywords. 3) Boost.Phoenix already uses _this (as a placeholder). In the Boost.Local case _this/this_ is both: 1) A placeholders because it will be "replaced" with the actual object pointer `this`. 2) And obviously a keyword. So what do I do? _this or this_? I might as well be consistent with another Boost library. Plus, if _this is also used in the function declaration (not just the definition) then it really acts as a placeholder. I am only 52% in favor of _this over this_ and I am happy to use the name that the reviewers find more correct. BTW, I couldn't find Phoenix docs that refer to _this-- does anyone have a link? Is there any other Boost library that uses either _this or this_? Thanks, --Lorenzo

AMDG On 11/14/2011 04:59 PM, Lorenzo Caminiti wrote:
In this email thread: http://lists.boost.org/Archives/boost/2011/04/179834.php
Three things where pointed out: 1) _ prefix is for placeholders. 2) _ postfix is for keywords. 3) Boost.Phoenix already uses _this (as a placeholder).
In the Boost.Local case _this/this_ is both: 1) A placeholders because it will be "replaced" with the actual object pointer `this`. 2) And obviously a keyword. So what do I do? _this or this_?
It should be this_. The way you're using it is not what I would consider a placeholder. If that were the definition of a placeholder than every reference should be considered a placeholder because the reference gets "replaced" with the actual object, which is absurd.
I might as well be consistent with another Boost library. Plus, if _this is also used in the function declaration (not just the definition) then it really acts as a placeholder. I am only 52% in favor of _this over this_ and I am happy to use the name that the reviewers find more correct.
BTW, I couldn't find Phoenix docs that refer to _this-- does anyone have a link? Is there any other Boost library that uses either _this or this_?
In Christ, Steven Watanabe

On Mon, Nov 14, 2011 at 9:01 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
On 11/14/2011 04:59 PM, Lorenzo Caminiti wrote:
In this email thread: http://lists.boost.org/Archives/boost/2011/04/179834.php
Three things where pointed out: 1) _ prefix is for placeholders. 2) _ postfix is for keywords. 3) Boost.Phoenix already uses _this (as a placeholder).
In the Boost.Local case _this/this_ is both: 1) A placeholders because it will be "replaced" with the actual object pointer `this`. 2) And obviously a keyword. So what do I do? _this or this_?
It should be this_. The way you're using it is not what I would consider a placeholder. If that were the definition of a placeholder than every reference should be considered a placeholder because the reference gets "replaced" with the actual object, which is absurd.
OK, I'm easily convinced one way or the other. Just to clarify this is how it will look like: // (a) using the keyword convention this_ int BOOST_LOCAL_FUNCTION_PARAMS(int x, const bind this_) { return x + this_->value; } BOOST_LOCAL_FUNCTION_NAME(l) int y = l(123); or // (b) using the placeholder convention _this int BOOST_LOCAL_FUNCTION_PARAMS(int x, const bind _this) { return x + _this->value; } BOOST_LOCAL_FUNCTION_NAME(l) int y = l(123); It sounds like most people think (a) is best so far because this_ plays the keyword (not placeholder) role in this context.
I might as well be consistent with another Boost library. Plus, if _this is also used in the function declaration (not just the definition) then it really acts as a placeholder. I am only 52% in favor of _this over this_ and I am happy to use the name that the reviewers find more correct.
BTW, I couldn't find Phoenix docs that refer to _this-- does anyone have a link? Is there any other Boost library that uses either _this or this_?
I still would like to look at _this/this_ in other Boot libraries. Does anyone have any link to docs, examples, etc for that? Thanks. --Lorenzo

Le 15/11/11 01:00, Lorenzo Caminiti a écrit : > On Mon, Nov 14, 2011 at 12:49 PM, Vicente J. Botet Escriba > <vicente.botet@wanadoo.fr> wrote: >> Le 10/11/11 06:31, Jeffrey Lee Hellrung, Jr. a écrit : >> >> Hi Lorenzo, here is my review. > Hi Vicente, thanks for your review! > >> I have not too much to say. The library is well designed and documented. > :) > >> Just some minor points: >> >> To be coherent with the other macros I would suggest >> BOOST_LOCAL_FUNCTION/BOOST_LOCAL_FUNCTION_END instead of >> BOOST_LOCAL_FUNCTION_PARAMS/BOOST_LOCAL_FUNCTION_NAME. > I have been considering this too because sometimes I get confused and > write BOOST_LOCAL_FUNCTION without the _PARAMS. The > BOOST_LOCAL_FUNCTION and BOOST_LOCAL_FUNTION_END names are also more > consistent with the early experimentation on local functions done by > Alexander Nasonov and Steven Watanabe > http://thread.gmane.org/gmane.comp.lib.boost.devel/168612. OTOH, I do > think that _PARAMS and _NAME are more descriptive names because they > clearly say what you specify using these macros and that is why I > ultimately decided to go with the more descriptive names. Yes, but the BOOST_LOCAL_BLOCK and BOOST_LOCAL_EXIT should be renamed BOOST_LOCAL_BLOCK_PARAMS, ... In addition the list contains the parameters as well as the bounds variables. > I have not strong feelings between these different names and I will > haply comply with the consensus reached during this review. Does > anyone else have an opinion? > >> Is there any possible optimization/portability improvement to add the return >> type to the macro for the local function? > The _only_ benefit in passing the result type within the macros is > that when you also specify the types of all bound variables the > library will not use Boost.Typeof. In other words, right now even if > you specify the types of all bound variables `[const] bind(type)[&] > var`, the library still has to use typeof to deduce the result type > because such a type is not directly passed to the macros. I consider > this a _very_ minor advantage largely outweighed by the better syntax > achieved by moving the result type outside the macro. > > This is somewhat stated in the docs by the 3rd sentence of this subsection: > https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_local/Advanced_Topics.html#boost_local.Advanced_Topics.specifying_bound_types Yes, I saw that. Don't you think that don't needing Boost.Typeof is a big advantage? There are some compilers that don't supports yet, Typeof. For them a specific macros would be welcome. > >> I would prefer BOOST_LOCAL_ON_SCOPE_EXIT to BOOST_LOCAL_EXIT even if longer >> it states clearly the intent of the block. I will not have any problem with >> the shorter BOOST_LOCAL_ON_SCOPE_EXIT. > I don't like BOOST_LOCAL_ON_SCOPE_EXIT because it's too long. How > about BOOST_SCOPED_EXIT, BOOST_SCOPED_BLOCK, BOOST_SCOPED_FUNCTION, > etc? The library will then be named Boost.Scoped and merged with > ScopeExit... if the merge is agreed on during this review. Yes, the names could depend on the name of the merged library, but I have no problem in no preficing these macros with BOOST_LIBNAME_ if we find a better name. BOOST_SCOPED_EXIT is to close to the existing macro BOOST_SCOPE_EXIT, which could trouble some of us. > >> IIUC the local blocks intent is to protect the block from unexpected >> updates. Couldn't in this case all the parameters be bound as const >> references by default? >> >> BOOST_LOCAL_BLOCK(sum) >> versus >> BOOST_LOCAL_BLOCK(const bind& sum) >> >> What about adding CONST in the name to reinforce the intent ? >> BOOST_LOCAL_CONST_BLOCK(sum) >> >> I will not have any problem with the shorter BOOST_CONST_BLOCK. > Not quite because you might want to modify one variable but make sure > that another one remains const. Therefore, I think it is best to leave > full control to the user that can specify which variable to be bound > by const and which not. For example: > > int x = 10; > int y = -10; > BOOST_LOCAL_BLOCK(const bind& x, bind& y) { // semantics: this block > of code does not change x but it changes y > assert(x>= 0); > y = x + 10; > } BOOST_LOCAL_BLOCK_END > > Also I think it's easier for the user if LOCAL_BLOCK has the same > binding interface of LOCAL_EXIT and LOCAL_FUNCTION_PARAMS (so no > implied const, etc). I don't see the utility for this use case. Anyway homogeneity is always a good thing. I said that because I was thinking on a possible language change to add a const attribute to a block [[const]] { // semantics: this block of code does not change any accessible variable assert(x>= 0); y = x + 10; // ERROR } >> As variadic macros are part of the new C++11 standard I will present the >> sequence interface as a workaround. > That could be done... I do think that Boost.Local is most useful with > C++03 because with C++11 you can use lambdas. However, even with C++03 > most (all?) compilers support variadics so the sequencing syntax could > indeed be presented as a "workaround" to apply when you want to be > 100% compliant with C++03 pp. > > That said, do you think it is heavy that the docs present all examples > in both syntaxes? If not, then I'd leave it as is. I was thinking to the macro BOOST_LOCAL_CONFIG_COMPLIANT, which could let think the user that using macros not provided by this mode are not "portable". I would say that they are not portable to non-c++11 compliant compilers. >> I have no preference between this_ and _this. Maybe it would be great to >> offer the possibility to the developer to name it. > You already can by #defining the configuration macro > BOOST_LOCAL_CONFIG_THIS_PARAM_NAME: > https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_LOCAL_CONFIG_THIS_PARAM_NAME.html > > As it was suggested, I'm thinking that I will change from this_ to > _this (to be consistent with Phoenix) and require to use _this in both > the local function declaration and implementation (and error at > compile-time if you use this instead of _this in the declaration but I > still can't error if you mistakenly use this instead of _this in the > definition :( ). I will also leave the config macro so the users can > change this name if they want/need to. > >> Can local functions have types that are typenames of the nesting function? >> e.g. is the following valid? >> >> template<typename T> >> void f() { >> >> BOOST_LOCAL_FUNCTION_PARAMS(T v) >> ... >> BOOST_LOCAL_FUNCTION_NAME(g); >> >> ... >> } > Yes, this is possible but you need to use the version of the macros > with the _TPL postfix: > https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_local/Tutorial.html#boost_local.Tutorial.templates OH, yes of course. > > >>> -------- >>> >>> Please state clearly whether you think this library should be accepted as >>> a >>> Boost library. >> Yes, the library should be accepted. > :) > >>> Other questions you may want to consider: >>> >>> - What is your evaluation of the design? >> The interface is clean and manage with all the corner cases in an elegant >> way. >>> - What is your evaluation of the implementation? >> I have not inspected it yet. I hope to have some time from here to the end >> of the review. > While looking at the implementation, also look at: > https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_local/Implementation.html > >>> - What is your evaluation of the documentation? >> Very good. >> >> I will add a reference to the ScopedExit library when introducing Local >> exits and the advantages of your approach respect the one in ScopedExit. >> >> When you say " No semicolon |;| is required after the ending macro." do you >> mean that if a ';' is used, no error occurs, or that ';' is not allowed? >> Other usages of "No xxx is required" should be checked also. > It just means that ; is not required. You can still put ; there, it > will work (I just triple checked :) ), but it is not required. That's > true all over (otherwise I say "it's required not to put it there"). > >> Could you add somewhere in the Implementation section, why the preprocessor >> can not parse default parameters as int y default 2 so you need a ',' >> between the variable and default? > There is already a footnote explaining the rationale of why = cannot > be used for default parameter values: > https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_local/Tutorial.html#ftn.boost_local.Tutorial.default_parameters.f0 Thanks, I missed it. > > I can expand this text indicating why default requires a preceding > comma. The comma is needed because the tokens `int x` can be anything > `mytype myvar` so the pp has no way to remove them to separate the > default value from the rest of the parameter declaration. The default > values need to be separated (stripped) because they are not part of > the function type and the library needs to build the function type for > some internal template metaprogramming manipulations. Also I need to > count the number of default parameter to select which functor to use > to declare the local function so it will have the call operator() for > each default parameter (the count is done by the pp and it requires to > identify which parameter has a default so it needs to be separated by > the rest of the parameter declaration-- the count cannot be done using > MPL because again default parameter value are not part of the function > type so I can't use template metaprogramming to inspect them, I need > to use pp metaprogramming). I know, this is quite a long story... No, the rationale you pointed out is enough. > >>> - What is your evaluation of the potential usefulness of the library? >> Quite useful. >>> - Did you try to use the library? With what compiler? Did you have any >>> problems? >> I have compiled the examples with darwin 4.2.1, clang-2.9,3.0 with and >> without c++0x enabled. > Cool. I've only tested with: > > GNU Compiler Collection (GCC) 4.5.1 (with and without C++11 features > enabled) on Ubuntu Linux 10. > GCC 4.3.4 on Cygwin. > Miscrosoft Visual Studio Compiler (MSVC) 8.0 on Windows XP. > > If the library is accepted a larger set of compilers will be supported > (if a compiler can handle Boost.Typeof and Boost.ScopeExit, there's no > reason that I can see why it should not be able to handle > Boost.Local). > >> I don't know why the Jamfile just build the executables and doesn't run >> them. Could you update the Jamfile so that we can run the examples? > Yes. I will also have to add tests to the library for now I only have examples. > >> Some errors > I looked at the errors below, they are not in Boost.Local: > 1) One error is because Boost.Lambda generates an internal error in > Darwing (add_using_boost_lambda.cpp has no Boost.Local code). I don't > know why... > 2) All other errors are because the add_optimizers.cpp intentionally > uses the auto classifier to show that Boost.Local works with auto and > register parameters. However, auto is deprecated so you get all the > other errors below. Glad to see that your library doesnt have any issue ;-) >>> - >>> - Lorenzo is proposing to add BOOST_IDENTITY_TYPE to boost/utility. See >>> >>> https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDENTITY_TYPE.html >>> - Likewise, Lorenzo is proposing to add BOOST_IDENTITY_VALUE to >>> boost/utility. See >>> >>> https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDENTITY_VALUE.html >> I guess that both macros could be better be included in Boost.Preprocessor. > IMO, it shouldn't go in Boost.Preprocessor because it is about C++ > types and not the pp (which is actually C). BTW, these macros are > really trivial, they don't use variadics at all, and I find > IDENTITY_TYPE very handy: > > #define BOOST_IDENTITY_TYPE(parenthesized_type) \ > boost::function_traits< void parenthesized_type>::arg1_type > > namespace boost { namespace aux { > template<typename T> > inline typename boost::add_reference<T>::type identity_value( > typename boost::add_reference<T>::type value) { > return value; > } > }} // namespace boost::aux > > #define BOOST_IDENTITY_VALUE(parenthesized_value) \ > boost::aux::identity_value parenthesized_value > > BOOST_IDENTITY_TYPE((boost::mpl::vector<char, int>)) > BOOST_IDENTITY_VALUE((boost::mpl::vector<char, int>::value)) I agree. See my answer to Jeffrey. > Thanks a lot for your review! You are welcome. Good luck, Vicente

On Mon, Nov 14, 2011 at 7:53 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 15/11/11 01:00, Lorenzo Caminiti a écrit :
On Mon, Nov 14, 2011 at 12:49 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 10/11/11 06:31, Jeffrey Lee Hellrung, Jr. a écrit :
Hi Lorenzo, here is my review.
Hi Vicente, thanks for your review!
I have not too much to say. The library is well designed and documented.
:)
Just some minor points:
To be coherent with the other macros I would suggest BOOST_LOCAL_FUNCTION/BOOST_LOCAL_FUNCTION_END instead of BOOST_LOCAL_FUNCTION_PARAMS/BOOST_LOCAL_FUNCTION_NAME.
I have been considering this too because sometimes I get confused and write BOOST_LOCAL_FUNCTION without the _PARAMS. The BOOST_LOCAL_FUNCTION and BOOST_LOCAL_FUNTION_END names are also more consistent with the early experimentation on local functions done by Alexander Nasonov and Steven Watanabe http://thread.gmane.org/gmane.comp.lib.boost.devel/168612. OTOH, I do think that _PARAMS and _NAME are more descriptive names because they clearly say what you specify using these macros and that is why I ultimately decided to go with the more descriptive names.
Yes, but the BOOST_LOCAL_BLOCK and BOOST_LOCAL_EXIT should be renamed BOOST_LOCAL_BLOCK_PARAMS, ...
In addition the list contains the parameters as well as the bounds variables.
Good point. If no one objects, I'm happy with: FUNCTION_PARAMS(params_and_bindings) --> FUNCTION(params_and_bindings) FUNCTION_NAME(name) --> FUNCTION_END(name)
I have not strong feelings between these different names and I will haply comply with the consensus reached during this review. Does anyone else have an opinion?
Is there any possible optimization/portability improvement to add the return type to the macro for the local function?
The _only_ benefit in passing the result type within the macros is that when you also specify the types of all bound variables the library will not use Boost.Typeof. In other words, right now even if you specify the types of all bound variables `[const] bind(type)[&] var`, the library still has to use typeof to deduce the result type because such a type is not directly passed to the macros. I consider this a _very_ minor advantage largely outweighed by the better syntax achieved by moving the result type outside the macro.
This is somewhat stated in the docs by the 3rd sentence of this subsection:
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
Yes, I saw that. Don't you think that don't needing Boost.Typeof is a big advantage? There are some compilers that don't supports yet, Typeof. For them a specific macros would be welcome.
Yes, I can add this feature by providing another macro like: /* no result type here */ FUNCTION_WITH_RESULT[_TPL]( result_type [, params_and_bindings] ) { ... } FUNCTION_END( [inline | recursive] name ) BLOCKS and EXITS always have void result so no need for an extra macro for them (if you specify the type for your bindings for BLOCKS and EXITS then they always use no typeof). That said, I need to closely look at the implementation to guarantee that no typeof is used when the result and binding types are specified in the macros.
I would prefer BOOST_LOCAL_ON_SCOPE_EXIT to BOOST_LOCAL_EXIT even if longer it states clearly the intent of the block. I will not have any problem with the shorter BOOST_LOCAL_ON_SCOPE_EXIT.
I don't like BOOST_LOCAL_ON_SCOPE_EXIT because it's too long. How about BOOST_SCOPED_EXIT, BOOST_SCOPED_BLOCK, BOOST_SCOPED_FUNCTION, etc? The library will then be named Boost.Scoped and merged with ScopeExit... if the merge is agreed on during this review.
Yes, the names could depend on the name of the merged library, but I have no problem in no preficing these macros with BOOST_LIBNAME_ if we find a better name. BOOST_SCOPED_EXIT is to close to the existing macro BOOST_SCOPE_EXIT, which could trouble some of us.
I sent another reply with considerations on possible names.
IIUC the local blocks intent is to protect the block from unexpected updates. Couldn't in this case all the parameters be bound as const references by default?
BOOST_LOCAL_BLOCK(sum) versus BOOST_LOCAL_BLOCK(const bind& sum)
What about adding CONST in the name to reinforce the intent ? BOOST_LOCAL_CONST_BLOCK(sum)
I will not have any problem with the shorter BOOST_CONST_BLOCK.
Not quite because you might want to modify one variable but make sure that another one remains const. Therefore, I think it is best to leave full control to the user that can specify which variable to be bound by const and which not. For example:
int x = 10; int y = -10; BOOST_LOCAL_BLOCK(const bind& x, bind& y) { // semantics: this block of code does not change x but it changes y assert(x>= 0); y = x + 10; } BOOST_LOCAL_BLOCK_END
Also I think it's easier for the user if LOCAL_BLOCK has the same binding interface of LOCAL_EXIT and LOCAL_FUNCTION_PARAMS (so no implied const, etc).
I don't see the utility for this use case. Anyway homogeneity is always a good thing. I said that because I was thinking on a possible language change to add a const attribute to a block
[[const]]
{ // semantics: this block of code does not change any accessible variable assert(x>= 0); y = x + 10; // ERROR }
Thorsten proposed something like that in N1613 when considering if a library could implement Contract Programming while ensuring assertion constant-correctness (see bottom of page 15): http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2004/n1613.pdf I saw that and asked Boosters if there was a way to program a "constant-block". You and Steven replied saying to look at Alexander's early work on local functions thus I started Boost.Local. So yes, the main use case that I always had in mind for local blocks is constant blocks ;) Language support would be nice but now you can do it with Boost.Local!
As variadic macros are part of the new C++11 standard I will present the sequence interface as a workaround.
That could be done... I do think that Boost.Local is most useful with C++03 because with C++11 you can use lambdas. However, even with C++03 most (all?) compilers support variadics so the sequencing syntax could indeed be presented as a "workaround" to apply when you want to be 100% compliant with C++03 pp.
That said, do you think it is heavy that the docs present all examples in both syntaxes? If not, then I'd leave it as is.
I was thinking to the macro BOOST_LOCAL_CONFIG_COMPLIANT, which could let think the user that using macros not provided by this mode are not "portable". I would say that they are not portable to non-c++11 compliant compilers.
I see. #define BOOST_LOCAL_CONFIG_COMPLIANT does two things: 1) Don't use variadics (and empty macro parameters). 2) Don't pass local types as template parameters (this makes a run-time local function call slower). Maybe I should split this one macro into two macros BOOST_LOCAL_CONFIG_NO_VARIADICS and BOOST_LOCAL_CONFIG_NO_LOCAL_TYPES_AS_TPARAMS. What do you think?
I have no preference between this_ and _this. Maybe it would be great to offer the possibility to the developer to name it.
You already can by #defining the configuration macro BOOST_LOCAL_CONFIG_THIS_PARAM_NAME:
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_LOCA...
As it was suggested, I'm thinking that I will change from this_ to _this (to be consistent with Phoenix) and require to use _this in both the local function declaration and implementation (and error at compile-time if you use this instead of _this in the declaration but I still can't error if you mistakenly use this instead of _this in the definition :( ). I will also leave the config macro so the users can change this name if they want/need to.
Can local functions have types that are typenames of the nesting function? e.g. is the following valid?
template<typename T> void f() {
BOOST_LOCAL_FUNCTION_PARAMS(T v) ... BOOST_LOCAL_FUNCTION_NAME(g);
... }
Yes, this is possible but you need to use the version of the macros with the _TPL postfix:
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
OH, yes of course.
--------
Please state clearly whether you think this library should be accepted as a Boost library.
Yes, the library should be accepted.
:)
Other questions you may want to consider:
- What is your evaluation of the design?
The interface is clean and manage with all the corner cases in an elegant way.
- What is your evaluation of the implementation?
I have not inspected it yet. I hope to have some time from here to the end of the review.
While looking at the implementation, also look at:
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
- What is your evaluation of the documentation?
Very good.
I will add a reference to the ScopedExit library when introducing Local exits and the advantages of your approach respect the one in ScopedExit.
When you say " No semicolon |;| is required after the ending macro." do you mean that if a ';' is used, no error occurs, or that ';' is not allowed? Other usages of "No xxx is required" should be checked also.
It just means that ; is not required. You can still put ; there, it will work (I just triple checked :) ), but it is not required. That's true all over (otherwise I say "it's required not to put it there").
Could you add somewhere in the Implementation section, why the preprocessor can not parse default parameters as int y default 2 so you need a ',' between the variable and default?
There is already a footnote explaining the rationale of why = cannot be used for default parameter values:
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
Thanks, I missed it.
I can expand this text indicating why default requires a preceding comma. The comma is needed because the tokens `int x` can be anything `mytype myvar` so the pp has no way to remove them to separate the default value from the rest of the parameter declaration. The default values need to be separated (stripped) because they are not part of the function type and the library needs to build the function type for some internal template metaprogramming manipulations. Also I need to count the number of default parameter to select which functor to use to declare the local function so it will have the call operator() for each default parameter (the count is done by the pp and it requires to identify which parameter has a default so it needs to be separated by the rest of the parameter declaration-- the count cannot be done using MPL because again default parameter value are not part of the function type so I can't use template metaprogramming to inspect them, I need to use pp metaprogramming). I know, this is quite a long story...
No, the rationale you pointed out is enough.
- What is your evaluation of the potential usefulness of the library?
Quite useful.
- Did you try to use the library? With what compiler? Did you have any problems?
I have compiled the examples with darwin 4.2.1, clang-2.9,3.0 with and without c++0x enabled.
Cool. I've only tested with:
GNU Compiler Collection (GCC) 4.5.1 (with and without C++11 features enabled) on Ubuntu Linux 10. GCC 4.3.4 on Cygwin. Miscrosoft Visual Studio Compiler (MSVC) 8.0 on Windows XP.
If the library is accepted a larger set of compilers will be supported (if a compiler can handle Boost.Typeof and Boost.ScopeExit, there's no reason that I can see why it should not be able to handle Boost.Local).
I don't know why the Jamfile just build the executables and doesn't run them. Could you update the Jamfile so that we can run the examples?
Yes. I will also have to add tests to the library for now I only have examples.
Some errors
I looked at the errors below, they are not in Boost.Local: 1) One error is because Boost.Lambda generates an internal error in Darwing (add_using_boost_lambda.cpp has no Boost.Local code). I don't know why... 2) All other errors are because the add_optimizers.cpp intentionally uses the auto classifier to show that Boost.Local works with auto and register parameters. However, auto is deprecated so you get all the other errors below.
Glad to see that your library doesnt have any issue ;-)
- - Lorenzo is proposing to add BOOST_IDENTITY_TYPE to boost/utility. See
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN... - Likewise, Lorenzo is proposing to add BOOST_IDENTITY_VALUE to boost/utility. See
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/BOOST_IDEN...
I guess that both macros could be better be included in Boost.Preprocessor.
IMO, it shouldn't go in Boost.Preprocessor because it is about C++ types and not the pp (which is actually C). BTW, these macros are really trivial, they don't use variadics at all, and I find IDENTITY_TYPE very handy:
#define BOOST_IDENTITY_TYPE(parenthesized_type) \ boost::function_traits< void parenthesized_type>::arg1_type
namespace boost { namespace aux { template<typename T> inline typename boost::add_reference<T>::type identity_value( typename boost::add_reference<T>::type value) { return value; } }} // namespace boost::aux
#define BOOST_IDENTITY_VALUE(parenthesized_value) \ boost::aux::identity_value parenthesized_value
BOOST_IDENTITY_TYPE((boost::mpl::vector<char, int>)) BOOST_IDENTITY_VALUE((boost::mpl::vector<char, int>::value))
I agree. See my answer to Jeffrey.
Thanks a lot for your review!
You are welcome.
Thanks. --Lorenzo

On Mon, Nov 14, 2011 at 8:32 PM, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
On Mon, Nov 14, 2011 at 7:53 PM, Vicente J. Botet Escriba
Is there any possible optimization/portability improvement to add the return type to the macro for the local function?
The _only_ benefit in passing the result type within the macros is that when you also specify the types of all bound variables the library will not use Boost.Typeof. In other words, right now even if you specify the types of all bound variables `[const] bind(type)[&] var`, the library still has to use typeof to deduce the result type because such a type is not directly passed to the macros. I consider this a _very_ minor advantage largely outweighed by the better syntax achieved by moving the result type outside the macro.
This is somewhat stated in the docs by the 3rd sentence of this subsection:
https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca...
Yes, I saw that. Don't you think that don't needing Boost.Typeof is a big advantage? There are some compilers that don't supports yet, Typeof. For them a specific macros would be welcome.
Yes, I can add this feature by providing another macro like:
/* no result type here */ FUNCTION_WITH_RESULT[_TPL]( result_type [, params_and_bindings] ) { ... } FUNCTION_END( [inline | recursive] name )
BLOCKS and EXITS always have void result so no need for an extra macro for them (if you specify the type for your bindings for BLOCKS and EXITS then they always use no typeof).
That said, I need to closely look at the implementation to guarantee that no typeof is used when the result and binding types are specified in the macros.
Unfortunately, I have looked at the implementation and Boost.Typeof is used by the FUNCTION_NAME macro to deduce the functor type :( It's a long story (it has to do with support for recursive local functions...) but I remember trying to not use typeof in NAME and I couldn't get around it. Anyway, I will try again to get rid of typeof in NAME. If I can do that (maybe even just for non recursive local functions), I will support this syntax where the return type is specified within the local function parameters (so I don't have to use another macro ..._WITH_RESULT). Expansion does not use typeof (maybe): int y = 10; BOOST_LOCAL_FUNCTION(int x, const bind(int) y, return int) { // (1) return x + y; } BOOST_LOCAL_FUNCTION_END(int) int z = int(1); // 11 Or, expansion uses typeof: int y = 10; int BOOST_LOCAL_FUNCTION(int x, const bind y) { // (2) return x + y; } BOOST_LOCAL_FUNCTION_END(int) int z = int(1); // 11 The same macro can deal with both syntaxes. If you specify the result type in both places, outside and inside the macro `int BOOST_LOCAL_FUNCTION(return int, ...) ...` then you'll get a compile-time error. IMPLEMENTATION NOTE: Parsing (1) and (2) might seem like arcane macro magic but it's rather simple. It uses Boost.Local KEYWORD detection and manipulation macros which are also at the basis the pp macros that parse the more complex Boost.Contract syntax: https://svn.boost.org/svn/boost/sandbox/local/libs/local/doc/html/boost_loca... Here's some sample code for the most curios: // if elem starts with return `return xyz abc ...` expands to // `xyz abc ...` (removing the leading return) otherwise // expands to nothing (eating the 1-tuple) #define FIND_RETURN(r, unused, elem) \ IF(KEYWORD_IS_RETURN_FRONT(elem), \ KEYWORD_RETURN_REMOVE_FRONT \ , \ TUPLE_EAT(1) \ )(elem) // apply macro above for each sequence element #define FIND_RESULT_TYPE(seq) \ SEQ_FOR_EACH(FIND_RETURN, ~, seq) // transform `int x, const bind(int) y, return unsigned int` // to pp-sequence (int x)(const bind(int) y)(return unsigned int) // and apply macro above on generated pp-sequence #define FIND_RESULT_TYPE(...) \ FIND_RESULT_TYPE_SEQ(VARIADIC_TO_SEQ(__VA_ARGS__) FIND_RESULT_TYPE(int x, const bind(int) y, return unsigned int) // expand to `unsigned int` :) Thanks. --Lorenzo

Le 17/11/11 17:51, Lorenzo Caminiti a écrit :
Unfortunately, I have looked at the implementation and Boost.Typeof is used by the FUNCTION_NAME macro to deduce the functor type :( It's a long story (it has to do with support for recursive local functions...) but I remember trying to not use typeof in NAME and I couldn't get around it. Anyway, I will try again to get rid of typeof in NAME. If I can do that (maybe even just for non recursive local functions), I will support this syntax where the return type is specified within the local function parameters (so I don't have to use another macro ..._WITH_RESULT).
Expansion does not use typeof (maybe):
int y = 10; BOOST_LOCAL_FUNCTION(int x, const bind(int) y, return int) { // (1) return x + y; } BOOST_LOCAL_FUNCTION_END(int) int z = int(1); // 11
Hi, thanks for the effort to limit the dependencies. Best, Vicente
participants (7)
-
Christian Holmquist
-
Jeffrey Lee Hellrung, Jr.
-
Krzysztof Czainski
-
Lorenzo Caminiti
-
Steven Watanabe
-
Thomas Klimpel
-
Vicente J. Botet Escriba