[local] Any "active Boost library author" in favor of Boost.Local?

Hello all, I will be honest: The fact that some of the people arguing for not including Boost.Local are "active Boost library authors" (Thomas, Joel, and Hartmut) seems to make their opinion weight more than the opinion of others that have also submitted a review for the library. Two questions: 1) Should reviews from "active Boost library authors" carry more weight? (This is /not/ a rhetoric question.) 2) Is there any "active Boost library author" out there that is in favor of including Boost.Local? (If so, please say so by replying to this thread.) Thanks a lot :) --Lorenzo

-----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Lorenzo Caminiti Sent: Friday, November 25, 2011 12:30 AM To: boost@lists.boost.org Subject: [boost] [local] Any "active Boost library author" in favor of Boost.Local?
Hello all,
I will be honest: The fact that some of the people arguing for not including Boost.Local are "active Boost library authors" (Thomas, Joel, and Hartmut) seems to make their opinion weight more than the opinion of others that have also submitted a review for the library.
Two questions:
1) Should reviews from "active Boost library authors" carry more weight? (This is /not/ a rhetoric question.)
2) Is there any "active Boost library author" out there that is in favor of including Boost.Local? (If so, please say so by replying to this thread.)
Weighting the reviews is the task (often very tricky) of the review manager. Whether the reviewer is an 'active library author' is just one weighting factor. I fall into that category, but I'd hate to think that my 'review' carried any weight just for that reason! Paul --- Paul A. Bristow, Prizet Farmhouse, Kendal LA8 8AB UK +44 1539 561830 07714330204 pbristow@hetp.u-net.com

lcaminiti wrote
Hello all,
I will be honest: The fact that some of the people arguing for not including Boost.Local are "active Boost library authors" (Thomas, Joel, and Hartmut) seems to make their opinion weight more than the opinion of others that have also submitted a review for the library.
Two questions:
1) Should reviews from "active Boost library authors" carry more weight? (This is /not/ a rhetoric question.)
2) Is there any "active Boost library author" out there that is in favor of including Boost.Local? (If so, please say so by replying to this thread.)
Hi Lorenzo, I don't think that the fact to be a library author will/should carry more weight on the review result. What is important is the arguments. I've been reading all the threads related to this review, and I have changed by perception of Boost.Local some times. I think that the last mail of Joel that has convinced me. The example shows an alternative that is clear enough and that should avoid compile errors that are difficult to digest. Of course, this examples is using a non local function, and even if you can think that this is not a valid alternative, as the definition is no local, when we see the simplicity and the better performances we could expect I think that most of the people will prefer this alternative to the one proposed by Boost.Local. I think that most of us would admit that local functions are useful, but as discussed during the review, Boost.Local doesn't provides local functions. The missing features been: * implicit access to the accessible variables * access to the non public functions of the embedding class (in case of a local function of a member function). That means that the interface of the local function is equivalent to the one we could write directly using a global function (I think that just don't needing to repeat the types is not a major advantage). This doesn't means that the work you have done is lost, as if I understand correctly you need to be able to define local functions to manage with the constraints of your Boost.Contract library. So, I vote for no acceptance of Boost.Local. Sorry for the change, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/local-Any-active-Boost-library-author-in-... Sent from the Boost - Dev mailing list archive at Nabble.com.

On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
So, I vote for no acceptance of Boost.Local.
Sorry for the change,
It's OK. I'm actually happy that the (stressful) discussion is at least helpful to clarify someone's decision one way or the other :) --Lorenzo

On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
I think that most of us would admit that local functions are useful, but as discussed during the review, Boost.Local doesn't provides local functions. The missing features been: * implicit access to the accessible variables
Yes, in the example below you explicitly have to say "bind this".
* access to the non public functions of the embedding class (in case of a local function of a member function).
Can you explain this point better? This example shows that you can access public, protected, and private members of a bound object (from within a member of the same class): #include <boost/local/function.hpp> #include <iostream> struct x { void f() { void BOOST_LOCAL_FUNCTION_PARAMS(bind this) { this_->priv(); this_->prot(); this_->publ(); } BOOST_LOCAL_FUNCTION_NAME(l) l(); } public: void publ() { std::cout << "public" << std::endl; } protected: void prot() { std::cout << "protected" << std::endl; } private: void priv() { std::cout << "private" << std::endl; } }; int main ( ) { x xx; xx.f(); return 0; } Thanks a lot for the clarification. --Lorenzo

Le 25/11/11 18:18, Lorenzo Caminiti a écrit :
On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
* access to the non public functions of the embedding class (in case of a local function of a member function). Can you explain this point better? This example shows that you can access public, protected, and private members of a bound object (from within a member of the same class):
#include<boost/local/function.hpp> #include<iostream>
struct x { void f() { void BOOST_LOCAL_FUNCTION_PARAMS(bind this) { this_->priv(); this_->prot(); this_->publ(); } BOOST_LOCAL_FUNCTION_NAME(l) l(); }
public: void publ() { std::cout<< "public"<< std::endl; } protected: void prot() { std::cout<< "protected"<< std::endl; } private: void priv() { std::cout<< "private"<< std::endl; } };
int main ( ) { x xx; xx.f(); return 0; } Sorry, I miss Boost.Local was able to do that. Where in the documentation can I find the local function can access the non-public interface?
Best, Vicente

On Fri, Nov 25, 2011 at 12:32 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 25/11/11 18:18, Lorenzo Caminiti a écrit :
On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
* access to the non public functions of the embedding class (in case of a local function of a member function).
Can you explain this point better? This example shows that you can access public, protected, and private members of a bound object (from within a member of the same class):
#include<boost/local/function.hpp> #include<iostream>
struct x { void f() { void BOOST_LOCAL_FUNCTION_PARAMS(bind this) { this_->priv(); this_->prot(); this_->publ(); } BOOST_LOCAL_FUNCTION_NAME(l) l(); }
public: void publ() { std::cout<< "public"<< std::endl; } protected: void prot() { std::cout<< "protected"<< std::endl; } private: void priv() { std::cout<< "private"<< std::endl; } };
int main ( ) { x xx; xx.f(); return 0; }
Sorry, I miss Boost.Local was able to do that. Where in the documentation can I find the local function can access the non-public interface?
It's nowhere in the docs... my bad :) On the contrary such a feature is not supported by the Phoenix solution *AFAIK* precisely because the functor is not local to the outer class (whereas the Local functor is local to the enclosing member function and therefore to the outer class). For example: #include <boost/phoenix/core.hpp> #include <boost/phoenix/function.hpp> #include <iostream> namespace impl { template<typename This> void f(This this_) { this_->publ(); // this_->prot(); // error :( // this_->priv(); // error :( } } BOOST_PHOENIX_ADAPT_FUNCTION(void, globalf, impl::f, 1) struct x { void f() { globalf(this)(); } public: void publ() { std::cout << "public" << std::endl; } protected: void prot() { std::cout << "protected" << std::endl; } private: void priv() { std::cout << "private" << std::endl; } }; int main ( ) { x xx; xx.f(); return 0; } DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to find. I'm sure Phoenix experts will be able to correct my example if such a possibility exists :) Thanks. --Lorenzo

On 11/25/2011 06:44 PM, Lorenzo Caminiti wrote:
On the contrary such a feature is not supported by the Phoenix solution *AFAIK* precisely because the functor is not local to the outer class (whereas the Local functor is local to the enclosing member function and therefore to the outer class). For example:
#include<boost/phoenix/core.hpp> #include<boost/phoenix/function.hpp> #include<iostream>
namespace impl { template<typename This> void f(This this_) { this_->publ(); // this_->prot(); // error :( // this_->priv(); // error :( } }
BOOST_PHOENIX_ADAPT_FUNCTION(void, globalf, impl::f, 1)
struct x { void f() { globalf(this)(); }
public: void publ() { std::cout<< "public"<< std::endl; } protected: void prot() { std::cout<< "protected"<< std::endl; } private: void priv() { std::cout<< "private"<< std::endl; } };
int main ( ) { x xx; xx.f(); return 0; }
DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to find. I'm sure Phoenix experts will be able to correct my example if such a possibility exists :)
It's not possible with Phoenix, though I believe there are hacks to make it possible somewhat. In any case I don't think this is even Phoenix code. There is no real phoenix expression involved, it's just a function being adapted into a function object.

Mathias Gaunard wrote:
DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to find. I'm sure Phoenix experts will be able to correct my example if such a possibility exists :)
It's not possible with Phoenix, though I believe there are hacks to make it possible somewhat.
I guess I would create a static member function and adapt it with Phoenix. Is this one of the hacks you imagined? Or were you more thinking in the direction of "friend" declarations? Regards, Thomas

On Fri, Nov 25, 2011 at 2:17 PM, Thomas Klimpel <Thomas.Klimpel@synopsys.com> wrote:
Mathias Gaunard wrote:
DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to find. I'm sure Phoenix experts will be able to correct my example if such a possibility exists :)
It's not possible with Phoenix, though I believe there are hacks to make it possible somewhat.
I guess I would create a static member function and adapt it with Phoenix. Is this one of the hacks you imagined? Or were you more thinking in the direction of "friend" declarations?
Yes, friendship will work as in the example below. However, please note that now the functor is not only non-local but it also has to explicitly override the class access level being declared as friend. In addition please also note that in order to declare the friendship you have to explicitly specify the bound type `int` (and you'll have to change the friendship declaration if you change the type of the bound variable a declared locally within the function). #include <boost/phoenix/core.hpp> #include <boost/phoenix/function.hpp> #include <iostream> namespace impl { template<typename This, typename A> void f(This this_, A a) { this_->publ(); this_->prot(); this_->priv(); } } BOOST_PHOENIX_ADAPT_FUNCTION(void, globalf, impl::f, 2) struct x { friend void impl::f<x*, int>(x*, int); void f() { int a; globalf(this, a)(); } public: void publ() { std::cout << "public" << std::endl; } protected: void prot() { std::cout << "protected" << std::endl; } private: void priv() { std::cout << "private" << std::endl; } }; int main ( ) { x xx; xx.f(); return 0; } That's to Vicente 2nd feature. To Vicente 1st feature instead: On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
I think that most of us would admit that local functions are useful, but as discussed during the review, Boost.Local doesn't provides local functions. The missing features been: * implicit access to the accessible variables
Please note that while it is true that with Boost.Local you have to explicitly say `bind this` (as in the local function declaration) with the Phoenix example you still have to explicitly say `this` (and in the call `globalf(this)();`). So in a sense both approaches fail to provide "implicit access to the accessible variables"... Did I understand the meaning of Vicente's 1st feature correctly? Thanks. --Lorenzo

On 11/25/2011 01:39 PM, Lorenzo Caminiti wrote:
On Fri, Nov 25, 2011 at 2:17 PM, Thomas Klimpel <Thomas.Klimpel@synopsys.com> wrote:
Mathias Gaunard wrote:
DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to find. I'm sure Phoenix experts will be able to correct my example if such a possibility exists :)
It's not possible with Phoenix, though I believe there are hacks to make it possible somewhat.
I guess I would create a static member function and adapt it with Phoenix. Is this one of the hacks you imagined? Or were you more thinking in the direction of "friend" declarations?
Yes, friendship will work as in the example below. However, please note that now the functor is not only non-local but it also has to explicitly override the class access level being declared as friend. In addition please also note that in order to declare the friendship you have to explicitly specify the bound type `int` (and you'll have to change the friendship declaration if you change the type of the bound variable a declared locally within the function).
#include<boost/phoenix/core.hpp> #include<boost/phoenix/function.hpp> #include<iostream>
namespace impl { template<typename This, typename A> void f(This this_, A a) { this_->publ(); this_->prot(); this_->priv(); } }
BOOST_PHOENIX_ADAPT_FUNCTION(void, globalf, impl::f, 2)
struct x { friend void impl::f<x*, int>(x*, int);
void f() { int a; globalf(this, a)(); }
public: void publ() { std::cout<< "public"<< std::endl; } protected: void prot() { std::cout<< "protected"<< std::endl; } private: void priv() { std::cout<< "private"<< std::endl; } };
int main ( ) { x xx; xx.f(); return 0; }
Observe: #include <boost/phoenix/core.hpp> #include <boost/phoenix/function.hpp> #include <iostream> struct x { void f() { // call it regularly: f_impl()(this); // turn it into a phoenix function: boost::phoenix::function<f_impl> localf = f_impl(); localf(this)(); } public: void publ() { std::cout << "public" << std::endl; } protected: void prot() { std::cout << "protected" << std::endl; } private: void priv() { std::cout << "private" << std::endl; } struct f_impl { typedef void result_type; template<typename This> void operator()(This this_) const { this_->publ(); this_->prot(); // error this_->priv(); // error } }; }; int main ( ) { x xx; xx.f(); return 0; }
That's to Vicente 2nd feature. To Vicente 1st feature instead:
On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
I think that most of us would admit that local functions are useful, but as discussed during the review, Boost.Local doesn't provides local functions. The missing features been: * implicit access to the accessible variables
Please note that while it is true that with Boost.Local you have to explicitly say `bind this` (as in the local function declaration) with the Phoenix example you still have to explicitly say `this` (and in the call `globalf(this)();`). So in a sense both approaches fail to provide "implicit access to the accessible variables"... Did I understand the meaning of Vicente's 1st feature correctly?
Thanks. --Lorenzo
_______________________________________________ Unsubscribe& other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Fri, Nov 25, 2011 at 2:42 PM, Thomas Heller <thom.heller@googlemail.com> wrote:
Observe:
First of all, thanks, these examples are helping me a _lot_ :) Look you can also turn the local function into the Phoenix function: #include <boost/local/function.hpp> #include <boost/phoenix/core.hpp> #include <boost/phoenix/function.hpp> #include <iostream> struct x { void f() { void BOOST_LOCAL_FUNCTION_PARAMS(bind this) { this_->publ(); this_->prot(); this_->priv(); } BOOST_LOCAL_FUNCTION_NAME(loc) // call it regularly: loc(); // turn it into a phoenix function: boost::phoenix::function<decltype(loc)> phoenixf = loc; phoenixf()(); } public: void publ() { std::cout << "public" << std::endl; } protected: void prot() { std::cout << "protected" << std::endl; } private: void priv() { std::cout << "private" << std::endl; } }; int main ( ) { x xx; xx.f(); return 0; } In fact you could even trivially write a macro to directly generate the Phoenix functor from the local scope: struct x { void f() { void BOOST_LOCAL_FUNCTION_PARAMS(bind this) { this_->publ(); this_->prot(); this_->priv(); } BOOST_LOCAL_FUNCTION_PHOENIX(phoenixloc) phoenixf()(); } public: void publ() { std::cout << "public" << std::endl; } protected: void prot() { std::cout << "protected" << std::endl; } private: void priv() { std::cout << "private" << std::endl; } }; Where: #define BOOST_LOCAL_FUNCTION_PHOENIX(name) \ BOOST_LOCAL_FUNCTION_NAME(BOOST_PP_CAT(boost_local_phoenix, __LINE__)) \ boost::phoenix::function<decltype(BOOST_PP_CAT(boost_local_phoenix, __LINE__))> phoenixf = BOOST_PP_CAT(boost_local_phoenix, __LINE__); Finally, I can trivially provide a BOOST_LOCAL_FUNCTION_TYPEOF(name) to replace the decltype above (so it doesn't have to use C++11 at all). Would this be useful? Is this what you meant when you proposed to try to use local functions to define Phoenix functions?
#include <boost/phoenix/core.hpp> #include <boost/phoenix/function.hpp> #include <iostream>
struct x { void f() { // call it regularly: f_impl()(this); // turn it into a phoenix function: boost::phoenix::function<f_impl> localf = f_impl(); localf(this)(); }
public: void publ() { std::cout << "public" << std::endl; } protected: void prot() { std::cout << "protected" << std::endl; } private: void priv() { std::cout << "private" << std::endl; }
struct f_impl { typedef void result_type; template<typename This> void operator()(This this_) const { this_->publ(); this_->prot(); // error this_->priv(); // error } }; };
int main ( ) { x xx; xx.f(); return 0; }
Thanks the clarifications. --Lorenzo

Le 25/11/11 20:39, Lorenzo Caminiti a écrit :
On Fri, Nov 25, 2011 at 2:17 PM, Thomas Klimpel <Thomas.Klimpel@synopsys.com> wrote:
Mathias Gaunard wrote:
DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to find. I'm sure Phoenix experts will be able to correct my example if such a possibility exists :) It's not possible with Phoenix, though I believe there are hacks to make it possible somewhat. I guess I would create a static member function and adapt it with Phoenix. Is this one of the hacks you imagined? Or were you more thinking in the direction of "friend" declarations? Yes, friendship will work as in the example below. However, please note that now the functor is not only non-local but it also has to explicitly override the class access level being declared as friend. In addition please also note that in order to declare the friendship you have to explicitly specify the bound type `int` (and you'll have to change the friendship declaration if you change the type of the bound variable a declared locally within the function).
You are right, if you use a global function, but in this case I think the best is to use a private function so that you have automatic access to all the members. I have a question Lorenzo, how do you reach to have access to the non-public members from the local function? Forget me if this is already explained in the documentation, just please, point where.
That's to Vicente 2nd feature. To Vicente 1st feature instead:
I think that most of us would admit that local functions are useful, but as discussed during the review, Boost.Local doesn't provides local functions. The missing features been: * implicit access to the accessible variables Please note that while it is true that with Boost.Local you have to explicitly say `bind this` (as in the local function declaration) with
On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote: the Phoenix example you still have to explicitly say `this` (and in the call `globalf(this)();`). So in a sense both approaches fail to provide "implicit access to the accessible variables"... Did I understand the meaning of Vicente's 1st feature correctly?
My concer was respect to local functions intergrated in the language, from which I would expect that we don't need to pass this a parameter and have direct access to all the functions and data accessible from the embedding function. Best, Vicente

On Fri, Nov 25, 2011 at 3:20 PM, Vicente J. Botet Escriba <vicente.botet@wanadoo.fr> wrote:
Le 25/11/11 20:39, Lorenzo Caminiti a écrit :
On Fri, Nov 25, 2011 at 2:17 PM, Thomas Klimpel <Thomas.Klimpel@synopsys.com> wrote:
Mathias Gaunard wrote:
DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to
find.
I'm sure Phoenix experts will be able to correct my example if such a possibility exists :)
It's not possible with Phoenix, though I believe there are hacks to make it possible somewhat.
I guess I would create a static member function and adapt it with Phoenix. Is this one of the hacks you imagined? Or were you more thinking in the direction of "friend" declarations?
Yes, friendship will work as in the example below. However, please note that now the functor is not only non-local but it also has to explicitly override the class access level being declared as friend. In addition please also note that in order to declare the friendship you have to explicitly specify the bound type `int` (and you'll have to change the friendship declaration if you change the type of the bound variable a declared locally within the function).
You are right, if you use a global function, but in this case I think the best is to use a private function so that you have automatic access to all the members.
I have a question Lorenzo, how do you reach to have access to the non-public members from the local function? Forget me if this is already explained in the documentation, just please, point where.
It's not in the docs :( AFAIU, it's because of the fix to C++03 defect #45 which made types declared within a class (inner, local, etc) see all members of the outer class as if they were automatically friends: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#45 So this works: #include <iostream> struct x { void f() { struct local { static void func() { priv(); prot(); publ(); } }; local::func(); } public: static void publ() { std::cout << "public" << std::endl; } protected: static void prot() { std::cout << "protected" << std::endl; } private: static void priv() { std::cout << "private" << std::endl; } }; int main ( ) { x xx; xx.f(); return 0; } That's my understanding. (Probably irrelevant here, but I investigated this issue 3+ years ago because if they didn't fix this defect (which they did) I'd have been able to prevent contract assertions to use non-public members which is what Eiffel, but N1962 does not prevent such an access so at the end this is a Contract Programming requirement up for "interpretation".)
That's to Vicente 2nd feature. To Vicente 1st feature instead:
On Fri, Nov 25, 2011 at 11:06 AM, Vicente Botet <vicente.botet@wanadoo.fr> wrote:
I think that most of us would admit that local functions are useful, but as discussed during the review, Boost.Local doesn't provides local functions. The missing features been: * implicit access to the accessible variables
Please note that while it is true that with Boost.Local you have to explicitly say `bind this` (as in the local function declaration) with the Phoenix example you still have to explicitly say `this` (and in the call `globalf(this)();`). So in a sense both approaches fail to provide "implicit access to the accessible variables"... Did I understand the meaning of Vicente's 1st feature correctly?
My concer was respect to local functions intergrated in the language, from which I would expect that we don't need to pass this a parameter and have direct access to all the functions and data accessible from the embedding function.
Makes sense (even if C++11 chosen not automatically bind the entire environment, that said they do provide the [&] which is a very short way to bind the entire environment). Thanks. --Lorenzo

On 11/25/2011 08:17 PM, Thomas Klimpel wrote:
Mathias Gaunard wrote:
DISCLAIMER: I apologize in advance if there's a way to do access priv and prot from the Phoenix global functor which I was not able to find. I'm sure Phoenix experts will be able to correct my example if such a possibility exists :)
It's not possible with Phoenix, though I believe there are hacks to make it possible somewhat.
I guess I would create a static member function and adapt it with Phoenix. Is this one of the hacks you imagined? Or were you more thinking in the direction of "friend" declarations?
There are ways of accessing privates without friendship as well. <http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html>

On 11/25/2011 05:06 PM, Vicente Botet wrote:
That means that the interface of the local function is equivalent to the one we could write directly using a global function (I think that just don't needing to repeat the types is not a major advantage).
Of course it's equivalent, it's a macro. The point is that struct f_ { T0& a; T1& b; T2& c; T3& d; f_(TO& a_, T1& b_, T2& c_, T3& d_) : a(a_), b(b_), c(c_), d(d_) { } R operator()(A0 const& arg0, A1 const& arg1) const { return arg1 * a + arg2 / b + sin(c) * cos(d); } }; f_ f(a, b, c, d); Is quite more verbose to write than R BOOST_LOCAL_FUNCTION_PARAMS( bind a, bind b, bind c, bind d , A0 const& arg0, A1 const& arg1 ) { return arg1 * a + arg2 / b + sin(c) * cos(d); } BOOST_LOCAL_FUNCTION_NAME(f) This macro automates the tedious forwarding of the context to a functor. It is, to me, its main use. With Phoenix, I would write it as // these two macros must be at file scope BOOST_PHOENIX_ADAPT_FUNCTION(R, sin_, sin, 1) BOOST_PHOENIX_ADAPT_FUNCTION(R, cos_, cos, 1) BOOST_AUTO(f, arg1 * a + arg2 / b + sin_(c) * cos_(d)); The Phoenix version comes with many disadvantages however that have already been covered, and it's not that much better at terseness and macro-less-ness than Boost.Local. I think it is apparent however that the BOOST_LOCAL_* macros are quite practical in comparison to the manually-written functor at the top.

Le 25/11/11 20:21, Mathias Gaunard a écrit :
On 11/25/2011 05:06 PM, Vicente Botet wrote:
That means that the interface of the local function is equivalent to the one we could write directly using a global function (I think that just don't needing to repeat the types is not a major advantage).
Of course it's equivalent, it's a macro.
The point is that
struct f_ { T0& a; T1& b; T2& c; T3& d;
f_(TO& a_, T1& b_, T2& c_, T3& d_) : a(a_), b(b_), c(c_), d(d_) { }
R operator()(A0 const& arg0, A1 const& arg1) const { return arg1 * a + arg2 / b + sin(c) * cos(d); } };
f_ f(a, b, c, d);
Is quite more verbose to write than
R BOOST_LOCAL_FUNCTION_PARAMS( bind a, bind b, bind c, bind d , A0 const& arg0, A1 const& arg1 ) { return arg1 * a + arg2 / b + sin(c) * cos(d); } BOOST_LOCAL_FUNCTION_NAME(f)
I was comparing it to R f(TO& a, T1& b, T2& c, T3& d, A0 const& arg0, A1 const& arg1) { return arg1 * a + arg2 / b + sin(c) * cos(d); } //... R r = f(a,b,c,d,a0,a1);
This macro automates the tedious forwarding of the context to a functor. It is, to me, its main use.
Forwarding the context could be only useful if the function is called several times, so the context is passed only once.
With Phoenix, I would write it as
// these two macros must be at file scope BOOST_PHOENIX_ADAPT_FUNCTION(R, sin_, sin, 1) BOOST_PHOENIX_ADAPT_FUNCTION(R, cos_, cos, 1)
BOOST_AUTO(f, arg1 * a + arg2 / b + sin_(c) * cos_(d));
The Phoenix version comes with many disadvantages however that have already been covered, and it's not that much better at terseness and macro-less-ness than Boost.Local.
I'm not seen this as an alternative to Boost.Local, as the goal is to been able to write the action using c++ statements. So the comparison is not fair.
I think it is apparent however that the BOOST_LOCAL_* macros are quite practical in comparison to the manually-written functor at the top.
I don't know if you have seen the example provided by Joel. If not please take a look. Best, Vicente

On 11/25/2011 09:09 PM, Vicente J. Botet Escriba wrote:
I was comparing it to
R f(TO& a, T1& b, T2& c, T3& d, A0 const& arg0, A1 const& arg1) { return arg1 * a + arg2 / b + sin(c) * cos(d); } //... R r = f(a,b,c,d,a0,a1);
Passing the variable in scope is useful for higher-order functions, that usually take a couple of arguments for the values operated on. You cannot pass extra args as arguments, short of having a partial evaluation mechanism. This is what function objects are for.

lcaminiti wrote:
Hello all,
I will be honest: The fact that some of the people arguing for not including Boost.Local are "active Boost library authors" (Thomas, Joel, and Hartmut) seems to make their opinion weight more than the opinion of others that have also submitted a review for the library.
Two questions:
1) Should reviews from "active Boost library authors" carry more weight? (This is /not/ a rhetoric question.)
2) Is there any "active Boost library author" out there that is in favor of including Boost.Local? (If so, please say so by replying to this thread.)
Boost.Local was dead to me as soon as I found out that you had to bind local variables. The only advantage of the proposed library is that the body of the function goes next to where it is used rather than somewhere else. That's probably doable with either lambda+bind or phoenix. Personally, I don't value the ability to put the implementation of the function just before where it is passed into another function because it tears down the abstraction that a named function provides and reduces modularity and testability. I think a lambda is a good thing only if its entire body is a single statement that is very clear and short like {_1 < _2} where just in-lining it is as succinct as using a named function. If you are binding local variables to a function that you pass to another function you are doing something relatively clever. The behavior of that function should probably have a name so that your intention is self documenting, and you might also want to test it. I'd rather people's code be clear than clever. The macros don't help on that score. Having Boost.Local in addition all the other libraries which overlap it in scope in Boost would just make using boost more confusing. I agree completely with Hartmut. Regards, Luke
participants (8)
-
Lorenzo Caminiti
-
Mathias Gaunard
-
Paul A. Bristow
-
Simonson, Lucanus J
-
Thomas Heller
-
Thomas Klimpel
-
Vicente Botet
-
Vicente J. Botet Escriba