[Lambda] Handling Bind/Lambda name clashes.
Im compiling in an environment which #includes boost::bind.hpp, so I can't
get
away from it! I'd like to use Boost.Lambda sometimes, but run into namespace
clashes.
This code snippet works...
#include
So I'm having an issue with running an executable which statically links in the boost thread and system libraries on a SUSE Linux 64-bit computer. The static libraries are from boost 1.35.0. I also link with a 3rd party .so library. This library pulls in another version of the boost thread library in a .so, which is version 1.44.0. Depending on how I run our program, I get a crash in this 3rd party libraries call stack when it looks like it is trying to create a boost thread. When I removed our code that uses the boost libraries, everything worked fine. When I remove the 3rd party library, everything works fine. I'm not familiar with how programs work under this circumstance. Could this mixing of boost versions be a legitimate problem? Is the 3rd party library trying to call a boost function in our statically linked code under certain circumstances, causing the crash? Thanks, Tom
On Tue, Apr 5, 2011 at 2:06 PM, Robert Jones
Im compiling in an environment which #includes boost::bind.hpp, so I can't get away from it! I'd like to use Boost.Lambda sometimes, but run into namespace clashes. This code snippet works... #include
#include #include #include <vector> #include <numeric> // and also this... #include struct X { int f( ) const { return 1; } }; int sum( int a, int b ) { return a + b; } int main( ) { boost::lambda::placeholder1_type x; boost::lambda::placeholder2_type y; std::vector<X> v; std::accumulate( boost::begin( v ), boost::end( v ), 0, bind( sum, x, bind( &X::f, y ) ) ); } but as soon as I extract the innermost bind into a Boost.Function, I seem to need to fully qualify all the binds, ie int main( ) { boost::lambda::placeholder1_type x; boost::lambda::placeholder2_type y; std::vector<X> v; boost::function my_sum = bind( sum, x, y ); std::accumulate( boost::begin( v ), boost::end( v ), 0, boost::lambda::bind( my_sum, x, bind( &X::f, y ) ) ); } Is there any easy way around this? It would be nice to able to name my inner binds in a meaningful way, but all the explicit qualification gets a bit cumbersome! Thx - Rob.
Your testcase works me. Do you have a "using namespace boost;" somewhere in your headers? Putting a "using boost::lambda::bind;" before your calls to bind works for me, if you answered the previous question with yes.
Robert Jones wrote: ...
int main( ) { boost::lambda::placeholder1_type x; boost::lambda::placeholder2_type y;
std::vector<X> v;
std::accumulate( boost::begin( v ), boost::end( v ), 0, bind( sum, x, bind( &X::f, y ) ) ); }
You're relying on argument-dependent lookup here and it works only because x and y happen to be in namespace boost::lambda. A using declaration for boost::lambda::bind: using boost::lambda::bind; should be a better choice.
On Tue, Apr 5, 2011 at 2:27 PM, Peter Dimov
using boost::lambda::bind;
should be a better choice.
Hello Peter
Yes, that was my first thought too. But this code still has ambiguity
issues.
#include
Robert Jones wrote:
On Tue, Apr 5, 2011 at 2:27 PM, Peter Dimov
wrote: using boost::lambda::bind;
should be a better choice.
Hello Peter
Yes, that was my first thought too. But this code still has ambiguity issues.
Yes, you're right, it has. Since boost::function is in namespace boost, the compiler still finds boost::bind via argument-dependent lookup. I'm afraid that you'll have to qualify the ambiguous bind: namespace ll = boost::lambda; ll::bind( my_sum, ... );
On 4/5/2011 10:46 PM, Peter Dimov wrote:
Robert Jones wrote:
On Tue, Apr 5, 2011 at 2:27 PM, Peter Dimov
wrote: using boost::lambda::bind;
should be a better choice.
Hello Peter
Yes, that was my first thought too. But this code still has ambiguity issues.
Yes, you're right, it has. Since boost::function is in namespace boost, the compiler still finds boost::bind via argument-dependent lookup.
Yuk. Is it ever desirable for an argument of type boost::function to cause lookup in namespace boost? Probably not, right? That would argue for moving boost::function into an ADL-blocker namespace. And perhaps boost::bind and its placeholders should also be in an ADL-blocker namespace, but I seem to recall that the placeholders are not in any namespace for legacy reasons, is that right? -- Eric Niebler BoostPro Computing http://www.boostpro.com
At Wed, 06 Apr 2011 02:41:45 +0700, Eric Niebler wrote:
On 4/5/2011 10:46 PM, Peter Dimov wrote:
Robert Jones wrote:
On Tue, Apr 5, 2011 at 2:27 PM, Peter Dimov
wrote: using boost::lambda::bind;
should be a better choice.
Hello Peter
Yes, that was my first thought too. But this code still has ambiguity issues.
Yes, you're right, it has. Since boost::function is in namespace boost, the compiler still finds boost::bind via argument-dependent lookup.
Yuk. Is it ever desirable for an argument of type boost::function to cause lookup in namespace boost? Probably not, right? That would argue for moving boost::function into an ADL-blocker namespace.
And perhaps boost::bind and its placeholders should also be in an ADL-blocker namespace, but I seem to recall that the placeholders are not in any namespace for legacy reasons, is that right?
At this point, if such legacy compilers need to be supported, perhaps it makes sense to put the placeholders in a namespace conditionally, for all the other compilers? I wonder if it would be a good idea to have a Boost-wide policy that says something like, Librarry interfaces should not be compromised in any way for compilers shipped more than 10 years ago/not supported by their manufacturer/<appropriate other criterion here> -- Dave Abrahams BoostPro Computing http://www.boostpro.com
On Tue, Apr 5, 2011 at 9:22 PM, Dave Abrahams
At Wed, 06 Apr 2011 02:41:45 +0700, Eric Niebler wrote:
And perhaps boost::bind and its placeholders should also be in an ADL-blocker namespace, but I seem to recall that the placeholders are not in any namespace for legacy reasons, is that right?
At this point, if such legacy compilers need to be supported, perhaps it makes sense to put the placeholders in a namespace conditionally, for all the other compilers?
I wonder if it would be a good idea to have a Boost-wide policy that says something like,
Librarry interfaces should not be compromised in any way for compilers shipped more than 10 years ago/not supported by their manufacturer/<appropriate other criterion here>
From my point of view the problem of the _1, _2, _3, etc placeholders in the
Whatever policy might apply henceforth I'd imagine that moving the
Boost.Bind
placeholders out of the global namespace would be completely out of the
question
at this point.
presence of #include
Eric Niebler wrote:
Yuk. Is it ever desirable for an argument of type boost::function to cause lookup in namespace boost? Probably not, right? That would argue for moving boost::function into an ADL-blocker namespace.
Nothing here is specific to boost::function. By this same logic, nothing should ever be in namespace boost. You could very well make the case that, indeed, nothing but subnamespaces should be in boost. In most circumstances you would be right. But the reason everything is in boost is that everything that is accepted into the standard would move into std, and putting everything in boost allows us to catch problems that would in any case occur when the components are placed in std. And in fact, the original problem presents itself with std::function (or std::anything else, for that matter) and std::bind as well.
On 4/6/2011 5:12 AM, Peter Dimov wrote:
Eric Niebler wrote:
Yuk. Is it ever desirable for an argument of type boost::function to cause lookup in namespace boost? Probably not, right? That would argue for moving boost::function into an ADL-blocker namespace.
Nothing here is specific to boost::function. By this same logic, nothing should ever be in namespace boost.
Precisely. :-)
You could very well make the case that, indeed, nothing but subnamespaces should be in boost.
I'm not making that case, exactly. I'm saying that boost::function should actually be defined in boost::function_adl_block and be imported into the boost namespace with a using declaration.
In most circumstances you would be right. But the reason everything is in boost is that everything that is accepted into the standard would move into std, and putting everything in boost allows us to catch problems that would in any case occur when the components are placed in std. And in fact, the original problem presents itself with std::function (or std::anything else, for that matter) and std::bind as well.
Are you saying that Boost can never improve on what's in the standard? I see no reason for boost::function to be bug-for-bug compatible with std::function. -- Eric Niebler BoostPro Computing http://www.boostpro.com
On Wed, Apr 6, 2011 at 11:53 AM, Eric Niebler
On 4/6/2011 5:12 AM, Peter Dimov wrote:
You could very well make the case that, indeed, nothing but subnamespaces should be in boost.
I'm not making that case, exactly. I'm saying that boost::function should actually be defined in boost::function_adl_block and be imported into the boost namespace with a using declaration.
Forgiver my ignorance here, but if you do that which namespaces are then considered for ADL? boost, boost::function_adl_block or both? Thx - Rob.
AMDG On 04/06/2011 04:02 AM, Robert Jones wrote:
On Wed, Apr 6, 2011 at 11:53 AM, Eric Niebler
wrote: On 4/6/2011 5:12 AM, Peter Dimov wrote:
You could very well make the case that, indeed, nothing but subnamespaces should be in boost.
I'm not making that case, exactly. I'm saying that boost::function should actually be defined in boost::function_adl_block and be imported into the boost namespace with a using declaration.
Forgiver my ignorance here, but if you do that which namespaces are then considered for ADL? boost, boost::function_adl_block or both?
ADL only considers the namespace that the type is originally defined in. Using declarations don't increase the set of associated namespaces. In Christ, Steven Watanabe
Eric Niebler wrote:
I'm saying that boost::function should actually be defined in boost::function_adl_block and be imported into the boost namespace with a using declaration.
This makes no sense to me. boost::bind is the unconstrained function template found by ADL, not boost::function. You ought to be arguing that boost::bind should be in an ADL-blocking namespace. Of course this will break all code that relies on ADL to omit the boost:: qualification.
AMDG On 04/06/2011 10:46 AM, Peter Dimov wrote:
Eric Niebler wrote:
I'm saying that boost::function should actually be defined in boost::function_adl_block and be imported into the boost namespace with a using declaration.
This makes no sense to me. boost::bind is the unconstrained function template found by ADL, not boost::function. You ought to be arguing that boost::bind should be in an ADL-blocking namespace. Of course this will break all code that relies on ADL to omit the boost:: qualification.
The problem is that it's much easier to put a class in an ADL blocking namespace, than to put a class in al ADL blocking namespace: namespace bind_adl_block { template<class F> void bind(F f); } using bind_adl_block::bind; // bind can still be found by ADL The only way to do it is with a using directive: using namespace bin_adl_block; but this is fragile for other reasons. In Christ, Steven Watanabe
On 4/7/2011 1:02 AM, Steven Watanabe wrote:
AMDG
On 04/06/2011 10:46 AM, Peter Dimov wrote:
Eric Niebler wrote:
I'm saying that boost::function should actually be defined in boost::function_adl_block and be imported into the boost namespace with a using declaration.
This makes no sense to me. boost::bind is the unconstrained function template found by ADL, not boost::function. You ought to be arguing that boost::bind should be in an ADL-blocking namespace. Of course this will break all code that relies on ADL to omit the boost:: qualification.
The problem is that it's much easier to put a class in an ADL blocking namespace, than to put a class in al ADL blocking namespace:
Huh?
namespace bind_adl_block { template<class F> void bind(F f); } using bind_adl_block::bind; // bind can still be found by ADL
The only way to do it is with a using directive:
using namespace bin_adl_block;
but this is fragile for other reasons.
Wow, it seems there's a lot I don't know. Isn't this allowed: using bind_adl_block::bind; And what is wrong with leaving bind in the boost namespace as I was suggesting and define boost::function like this: namespace boost { namespace function_adl_block { template<class Sig> struct function {...}; } using function_adl_block::function; } Now the "boost" namespace is no longer associated with boost::function, and boost::bind won't be found by ADL. Unless I'm mistaken, and a quick test with comeauonline suggests I'm not. But Steven and Peter are usually right about this stuff, so I'll patiently wait to be corrected and learn. :-) -- Eric Niebler BoostPro Computing http://www.boostpro.com
AMDG On 04/06/2011 09:03 PM, Eric Niebler wrote:
On 4/7/2011 1:02 AM, Steven Watanabe wrote:
On 04/06/2011 10:46 AM, Peter Dimov wrote:
Eric Niebler wrote:
I'm saying that boost::function should actually be defined in boost::function_adl_block and be imported into the boost namespace with a using declaration.
This makes no sense to me. boost::bind is the unconstrained function template found by ADL, not boost::function. You ought to be arguing that boost::bind should be in an ADL-blocking namespace. Of course this will break all code that relies on ADL to omit the boost:: qualification.
The problem is that it's much easier to put a class in an ADL blocking namespace, than to put a class in al ADL blocking namespace:
Huh?
Oops. That should be "it's much easier to put a class in an ADL blocking namespace, than to put a /function/ in an ADL blocking namespace"
namespace bind_adl_block { template<class F> void bind(F f); } using bind_adl_block::bind; // bind can still be found by ADL
The only way to do it is with a using directive:
using namespace bin_adl_block;
but this is fragile for other reasons.
Wow, it seems there's a lot I don't know. Isn't this allowed:
using bind_adl_block::bind;
It's allowed, but it doesn't work, because a function imported via a using declaration /can/ be found by ADL.
And what is wrong with leaving bind in the boost namespace as I was suggesting and define boost::function like this:
namespace boost { namespace function_adl_block { template<class Sig> struct function {...}; } using function_adl_block::function; }
Now the "boost" namespace is no longer associated with boost::function, and boost::bind won't be found by ADL. Unless I'm mistaken, and a quick test with comeauonline suggests I'm not. But Steven and Peter are usually right about this stuff, so I'll patiently wait to be corrected and learn. :-)
Yes, you're correct about this. In Christ, Steven Watanabe
On Thu, Apr 7, 2011 at 3:01 PM, Steven Watanabe
AMDG
And what is wrong with leaving bind in the boost namespace as I was
suggesting and define boost::function like this:
namespace boost { namespace function_adl_block { template<class Sig> struct function {...}; } using function_adl_block::function; }
Now the "boost" namespace is no longer associated with boost::function, and boost::bind won't be found by ADL. Unless I'm mistaken, and a quick test with comeauonline suggests I'm not. But Steven and Peter are usually right about this stuff, so I'll patiently wait to be corrected and learn. :-)
Yes, you're correct about this.
Ok, this seems to be a resolution to the issue. How about this change, and is there anyone of greater boosty skills than me who'd do it? - Rob.
(fixing attribution...) On 5/23/2011 11:42 PM, Robert Jones wrote:
On Thu, Apr 7, 2011 at 3:01 PM, Steven Watanabe wrote:
At some point in time, Eric Niebler wrote:
And what is wrong with leaving bind in the boost namespace as I was suggesting and define boost::function like this:
namespace boost { namespace function_adl_block { template<class Sig> struct function {...}; } using function_adl_block::function; }
Now the "boost" namespace is no longer associated with boost::function, and boost::bind won't be found by ADL. Unless I'm mistaken, and a quick test with comeauonline suggests I'm not. But Steven and Peter are usually right about this stuff, so I'll patiently wait to be corrected and learn. :-)
Yes, you're correct about this.
Ok, this seems to be a resolution to the issue. How about this change, and is there anyone of greater boosty skills than me who'd do it?
I have nothing against this change (obviously, since I suggested it). And it probably wouldn't require a great deal of "boosty skill," either. I say try it and see what breaks. :-) It's probably a good general policy to move most/all types in Boost into ADL-blocking namespaces like above, except those for which there is reason to keep boost as an associated namespace. Of course, that's a big job and I don't volunteer, but would it pay to have this as a documented library development guideline? -- Eric Niebler BoostPro Computing http://www.boostpro.com
On Tue, Apr 5, 2011 at 11:46 AM, Peter Dimov
Robert Jones wrote:
On Tue, Apr 5, 2011 at 2:27 PM, Peter Dimov
wrote: using boost::lambda::bind;
should be a better choice.
Hello Peter
Yes, that was my first thought too. But this code still has ambiguity issues.
Yes, you're right, it has. Since boost::function is in namespace boost, the compiler still finds boost::bind via argument-dependent lookup. I'm afraid that you'll have to qualify the ambiguous bind:
namespace ll = boost::lambda; ll::bind( my_sum, ... );
I may have forgotten the real truth, but at one point I thought I knew that the compiler would do ADL on using-declarations, but not on names brought in via using-directive. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
Please ignore my incoherent babbling. Need sleep...
On Wed, Apr 6, 2011 at 12:16 PM, Dave Abrahams
On Tue, Apr 5, 2011 at 11:46 AM, Peter Dimov
wrote: Robert Jones wrote:
On Tue, Apr 5, 2011 at 2:27 PM, Peter Dimov
wrote: using boost::lambda::bind;
should be a better choice.
Hello Peter
Yes, that was my first thought too. But this code still has ambiguity issues.
Yes, you're right, it has. Since boost::function is in namespace boost, the compiler still finds boost::bind via argument-dependent lookup. I'm afraid that you'll have to qualify the ambiguous bind:
namespace ll = boost::lambda; ll::bind( my_sum, ... );
I may have forgotten the real truth, but at one point I thought I knew that the compiler would do ADL on using-declarations, but not on names brought in via using-directive.
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
-- Dave Abrahams BoostPro Computing http://www.boostpro.com
Sorry, I should have been clearer. This is exactly the code that doesn't
work for
me, with no namespace qualification of 'bind'.
I'm guessing that the use of a Boost.Function as an argument to bind causes
the
bind in the boost namespace to be considered, as well the bind in the
boost::lambda
namespace which is considered because of the use of Boost.Lambda
placeholders.
I just can't think of a tidy solution.
Thx
- Rob.
#include
participants (7)
-
Dave Abrahams
-
Eric Niebler
-
Magyar, Thomas J. CIV NAVAIR
-
Peter Dimov
-
Robert Jones
-
Steven Watanabe
-
Thomas Heller