[local_function] End scope function name declaration makes code hard to read.

(This is a feature request/inquiry.) I'm just now seriously starting to use local_function, and I'm finding that having to "visually parse" until the end of scope to determine the local function name makes the code much harder to read. Is it possible to declare the function name at the beginning of the scope? (I don't mind having to also register the function name at the end of the scope.) Something like: BLF2(add, (int), (int lhs, int rhs)) { return lhs + rhs; } BLF2_REGISTER(add); Having said, I don't see why needing an "ending macro" for the local function scope is a requirement (albeit my understanding of the library internals is limited to implementation annex of the documentation). Can't the start macro just expand to something like: //----------------------------- //Macro Generated Output Start. //----------------------------- //Local class definition. //Local class instance registration. //Out of class method definition starts here: inline void local_add::body(int& sum, const int& factor, const int& num) //----------------------------- //Macro Generated Output End. //----------------------------- //User generated content starts here: { return lhs + rhs; } Thanks, Mostafa

On Fri, Mar 15, 2013 at 2:33 PM, Mostafa
(This is a feature request/inquiry.)
I'm just now seriously starting to use local_function, and I'm finding that having to "visually parse" until the end of scope to determine the local function name makes the code much harder to read. Is it possible to declare the function name at the beginning of the scope? (I don't mind having to also register the function name at the end of the scope.) Something like:
BLF2(add, (int), (int lhs, int rhs)) { return lhs + rhs; } BLF2_REGISTER(add);
Having said, I don't see why needing an "ending macro" for the local function scope is a requirement (albeit my understanding of the library internals is limited to implementation annex of the documentation). Can't the start macro just expand to something like:
//----------------------------**- //Macro Generated Output Start. //----------------------------**- //Local class definition. //Local class instance registration. //Out of class method definition starts here: inline void local_add::body(int& sum, const int& factor, const int& num) //----------------------------**- //Macro Generated Output End. //----------------------------**-
//User generated content starts here: { return lhs + rhs; }
I'm wondering, can you be more specific in what the above would look like? I believe the present implementation of local functions does something like (very simplified) struct xyz_struct : call_base { /*override*/ void call() // BEGIN macro expansion { /* body provided by user between macro invocations */ } } foo = {}; // END macro expansion and I think clearly here the END macro needs to know the function name ("foo"). - Jeff

On Fri, Mar 15, 2013 at 2:33 PM, Mostafa
(This is a feature request/inquiry.)
I'm just now seriously starting to use local_function, and I'm finding that having to "visually parse" until the end of scope to determine the local function name makes the code much harder to read. Is it possible to declare the function name at the beginning of the scope? (I don't mind having to also register the function name at the end of the scope.) Something like:
BLF2(add, (int), (int lhs, int rhs)) { return lhs + rhs; } BLF2_REGISTER(add);
To repeat the name is a bad idea because you duplicate that information. Just use a code comment after the result type to do that: void /* add */ BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) { sum += factor * num; } BOOST_LOCAL_FUNCTION_NAME(add)
Having said, I don't see why needing an "ending macro" for the local function scope is a requirement
[5] Rationale. The local function name must be passed to the macro BOOST_LOCAL_FUNCTION_NAME ending the function definition so this macro can declare a local variable with the local function name to hold the local function object. Therefore the local function name cannot be specified within the BOOST_LOCAL_FUNCTION and it must appear instead after the local function body (even if that differs from the usual C++ function declaration syntax). http://www.boost.org/doc/libs/1_53_0/libs/local_function/doc/html/boost_loca...
(albeit my understanding of the library internals is limited to implementation annex of the documentation). Can't the start macro just expand to something like:
Unfortunately not :( The Implementation section is just a very simplified example of what the macros generate: Note The code listed here can be used by curious readers and library maintainers as a reference in trying to understand the library source code. There is absolutely no guarantee that the library implementation uses the exact code listed here. Look at the source code, there are a couple of code comments that mention "here's why the name is needed here" but you have to dig into the code...
//----------------------------- //Macro Generated Output Start. //----------------------------- //Local class definition. //Local class instance registration. //Out of class method definition starts here: inline void local_add::body(int& sum, const int& factor, const int& num) //----------------------------- //Macro Generated Output End. //-----------------------------
//User generated content starts here: { return lhs + rhs; }
Thanks,
Mostafa
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
HTH, --Lorenzo

On Fri, 15 Mar 2013 15:20:32 -0700, Lorenzo Caminiti
On Fri, Mar 15, 2013 at 2:33 PM, Mostafa
wrote: (This is a feature request/inquiry.)
I'm just now seriously starting to use local_function, and I'm finding that having to "visually parse" until the end of scope to determine the local function name makes the code much harder to read. Is it possible to declare the function name at the beginning of the scope? (I don't mind having to also register the function name at the end of the scope.) Something like:
BLF2(add, (int), (int lhs, int rhs)) { return lhs + rhs; } BLF2_REGISTER(add);
To repeat the name is a bad idea because you duplicate that information. Just use a code comment after the result type to do that:
void /* add */ BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) { sum += factor * num; } BOOST_LOCAL_FUNCTION_NAME(add)
HTH, --Lorenzo
(I am going to respond in two posts, since the discussion will most likely split into two subthreads.) Thanks, unfortunately I think this is a worst idea. It's very easy for the comment and the code to get out of sync and there's no way the compiler will catch it, and anyways you're still duplicating information. With the alternative, I believe there is a way to jerry-rig a compiler error if the beginning and ending function names don't match (given my limited understanding of the implementation). The first macro will incorporate the function name into the name of the registering object, and the second second macro will incorporate the function name into the name of the local functor object, and will register the latter with the former. Using the example in the implementation annex, this is what it would like (yes, it may not be too wise to use that example, but in the absence of an alternative that's the best I can come up with): //------------ //First Macro. //------------ BLF2(add, (int), (int lhs, int rhs)) expands to: //Some stuff //Declare but don't initialize the registering object: casting_func add_casting; //------------ //Second Macro //------------ //BLF2_REGISTER(add) expands to: //Some other stuff //Register the local functor object using the object expanded to by the beginning macro add_casting.register(&add_local, &local_add::call); Hence, if there's any misspelling of the function name in either of the macros, a compiler error should ensue. (Anyways, I think my second post might make this entire exercise moot.) Thanks, Mostafa

On Fri, Mar 15, 2013 at 6:48 PM, Mostafa
On Fri, 15 Mar 2013 15:20:32 -0700, Lorenzo Caminiti
wrote: On Fri, Mar 15, 2013 at 2:33 PM, Mostafa
wrote: (This is a feature request/inquiry.)
I'm just now seriously starting to use local_function, and I'm finding that having to "visually parse" until the end of scope to determine the local function name makes the code much harder to read. Is it possible to declare the function name at the beginning of the scope? (I don't mind having to also register the function name at the end of the scope.) Something like:
BLF2(add, (int), (int lhs, int rhs)) { return lhs + rhs; } BLF2_REGISTER(add);
To repeat the name is a bad idea because you duplicate that information. Just use a code comment after the result type to do that:
void /* add */ BOOST_LOCAL_FUNCTION(const bind factor, bind& sum, int num) { sum += factor * num; } BOOST_LOCAL_FUNCTION_NAME(add)
HTH, --Lorenzo
(I am going to respond in two posts, since the discussion will most likely split into two subthreads.) Thanks, unfortunately I think this is a worst idea. It's very easy for the comment and the code to get out of sync and there's no way the compiler will catch it, and anyways you're still duplicating information. With the alternative, I believe there is a way to jerry-rig a compiler error if the beginning and ending function names don't match (given my limited understanding of the implementation). The first macro will incorporate the function name into the name of the registering object, and the second second macro will incorporate the function name into the name of the local functor object, and will register the latter with the former. Using the example in the implementation annex, this is what it would like (yes, it may not be too wise to use that example, but in the absence of an alternative that's the best I can come up with):
//------------ //First Macro. //------------ BLF2(add, (int), (int lhs, int rhs)) expands to:
Again, I won't provide this API because it duplicates the local function name given that the name is necessary for the ending macro (if you want the name at the beginning, where it is neither necessary nor sufficient, use a code comment, program your own macro that duplicate the information, etc).
//Some stuff //Declare but don't initialize the registering object: casting_func add_casting;
//------------ //Second Macro //------------ //BLF2_REGISTER(add) expands to:
//Some other stuff //Register the local functor object using the object expanded to by the beginning macro add_casting.register(&add_local, &local_add::call);
Hence, if there's any misspelling of the function name in either of the macros, a compiler error should ensue. (Anyways, I think my second post might make this entire exercise moot.)
Thanks,
Mostafa
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
-- --Lorenzo

On Fri, 15 Mar 2013 15:20:32 -0700, Lorenzo Caminiti
On Fri, Mar 15, 2013 at 2:33 PM, Mostafa
wrote: (This is a feature request/inquiry.)
I'm just now seriously starting to use local_function, and I'm finding that having to "visually parse" until the end of scope to determine the local function name makes the code much harder to read.[snip] Having said, I don't see why needing an "ending macro" for the local function scope is a requirement
[5] Rationale. The local function name must be passed to the macro BOOST_LOCAL_FUNCTION_NAME ending the function definition so this macro can declare a local variable with the local function name to hold the local function object. Therefore the local function name cannot be specified within the BOOST_LOCAL_FUNCTION and it must appear instead after the local function body (even if that differs from the usual C++ function declaration syntax).
http://www.boost.org/doc/libs/1_53_0/libs/local_function/doc/html/boost_loca...
Maybe I wasn't too clear in my original post. I can't see why the method
body can't be defined after the local function object variable
declaration. Declare, but don't define the method in the local class, and
then at the very end of all which the first macro expands to, "define" the
said method without the method body. So when the user completes the first
macro with "{ ... blah ...}", the latter completes the method definition.
Hence, no need for a second macro. For lack of a better example, I will
use the same example from implementation annex:
#define BFL2(add, (void), (const bind factor, bind& sum, int num)) \
struct local_add : virtual_func::interface { \
explicit local_add(int& _sum, const int& _factor) \
: sum_(_sum), factor_(_factor) {} \
inline void operator()(const int& num) { \
body(sum_, factor_, num); \
} \
inline static void call(void* obj, const int& num) { \
local_add* self = static_cast
Unfortunately not :( The Implementation section is just a very simplified example of what the macros generate:
Note The code listed here can be used by curious readers and library maintainers as a reference in trying to understand the library source code. There is absolutely no guarantee that the library implementation uses the exact code listed here.
Look at the source code, there are a couple of code comments that mention "here's why the name is needed here" but you have to dig into the code... [snip] HTH, --Lorenzo
Yes, I did see that, and did do "some" looking into the source. I was hoping to short-circuit some of that research with your insights. Thanks, Mostafa

AMDG On 03/15/2013 07:28 PM, Mostafa wrote:
On Fri, 15 Mar 2013 15:20:32 -0700, Lorenzo Caminiti
wrote: Maybe I wasn't too clear in my original post. I can't see why the method body can't be defined after the local function object variable declaration.
C++11 9.3: "A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition." In Christ, Steven Watanabe

On Fri, Mar 15, 2013 at 7:28 PM, Mostafa
On Fri, 15 Mar 2013 15:20:32 -0700, Lorenzo Caminiti
wrote: On Fri, Mar 15, 2013 at 2:33 PM, Mostafa
wrote: (This is a feature request/inquiry.)
I'm just now seriously starting to use local_function, and I'm finding that having to "visually parse" until the end of scope to determine the local function name makes the code much harder to read.[snip]
Having said, I don't see why needing an "ending macro" for the local function scope is a requirement
[5] Rationale. The local function name must be passed to the macro BOOST_LOCAL_FUNCTION_NAME ending the function definition so this macro can declare a local variable with the local function name to hold the local function object. Therefore the local function name cannot be specified within the BOOST_LOCAL_FUNCTION and it must appear instead after the local function body (even if that differs from the usual C++ function declaration syntax).
http://www.boost.org/doc/libs/1_53_0/libs/local_function/doc/html/boost_loca...
Maybe I wasn't too clear in my original post. I can't see why the method body can't be defined after the local function object variable declaration. Declare, but don't define the method in the local class, and then at the very end of all which the first macro expands to, "define" the said method without the method body. So when the user completes the first macro with "{ ... blah ...}", the latter completes the method definition. Hence, no need for a second macro. For lack of a better example, I will use the same example from implementation annex:
#define BFL2(add, (void), (const bind factor, bind& sum, int num)) \ struct local_add : virtual_func::interface { \ explicit local_add(int& _sum, const int& _factor) \ : sum_(_sum), factor_(_factor) {} \ inline void operator()(const int& num) { \ body(sum_, factor_, num); \ } \ inline static void call(void* obj, const int& num) { \ local_add* self = static_cast
(obj); \ self->body(self->sum_, self->factor_, num); \ } \ private: \ int& sum_; \ const int& factor_; \ inline void body(int& sum, const int& factor, const int& num); \ } add_local(sum, factor); \ casting_func add_casting(&add_local, &local_add::call); \ \ //DANGLING DEFINITION \ inline void local_add::body(int& sum, const int& factor, const int& num)
//Usage: BFL2(add, (void), (const bind factor, bind& sum, int num))
{ sum += factor * num; }
Note the "DANGLING DEFINITION" section.
Mostafa, on which compiler did you try to compile the "dangling definition" above in a local scope? As Steven also pointed out, unfortunately this is not valid C++: int main() { // local scope struct local_add { inline void body(); }; inline void local_add::body() // Invalid :( { } return 0; }
Unfortunately not :( The Implementation section is just a very simplified example of what the macros generate:
Note The code listed here can be used by curious readers and library maintainers as a reference in trying to understand the library source code. There is absolutely no guarantee that the library implementation uses the exact code listed here.
Look at the source code, there are a couple of code comments that mention "here's why the name is needed here" but you have to dig into the code... [snip] HTH, --Lorenzo
Yes, I did see that, and did do "some" looking into the source. I was hoping to short-circuit some of that research with your insights.
There's a number of tricks in the implementation especially to pass the local function as a template parameter and to speed up run-time... sorry but you'll just have to dig into the code details if you are interested about the internals of the library (there are code comments that should illustrate at least the critical ideas in the code). HTH, --Lorenzo

On Mon, 18 Mar 2013 08:43:34 -0700, Lorenzo Caminiti
Mostafa, on which compiler did you try to compile the "dangling definition" above in a local scope? As Steven also pointed out, unfortunately this is not valid C++:
int main() { // local scope struct local_add { inline void body(); }; inline void local_add::body() // Invalid :( { } return 0; }
Yes, you're both right. I was too hasty with that suggestion and didn't test it before posting it. Which is funny, because it's the third time I made that very same mistake ...
participants (4)
-
Jeffrey Lee Hellrung, Jr.
-
Lorenzo Caminiti
-
Mostafa
-
Steven Watanabe