once again: boost.bind namespace conflicts and how to solve them

I wonder if it makes sense to write an additional header for boost.bind (and maybe boost.function) that provides the library interfaces meeting the 'modern' boost requirements, i.e.: a) this header should be placed in the bind subdirectory, e.g. boost/bind/bind.hpp b) this header should introduce a separate namespace 'bind' or 'function' to avoid the well-known namespace clashes with boost::lambda that are _really_ annoying. c) this header should not declare the placeholders in an anomymous namespace. (I don't know what was the intention behind that but it makes it impossible to write 'using boost::_1') Comments? Stefan

Stefan Slapeta wrote:
I wonder if it makes sense to write an additional header for boost.bind (and maybe boost.function) that provides the library interfaces meeting the 'modern' boost requirements, i.e.:
I'm really not sure what do you mean by "modern" boost requirements.
a) this header should be placed in the bind subdirectory, e.g. boost/bind/bind.hpp
What purpose does that serve? Why not boost/bind/bind/bind.hpp?
b) this header should introduce a separate namespace 'bind' or 'function' to avoid the well-known namespace clashes with boost::lambda that are _really_ annoying.
Again, what purpose would that serve? The only name that bind.hpp "reserves" in boost is 'bind'. Defining a namespace 'bind' still reserves the same name in boost, namely, 'bind', except that user code is now uglier.
c) this header should not declare the placeholders in an anomymous namespace. (I don't know what was the intention behind that but it makes it impossible to write 'using boost::_1')
The original intent has been to make the placeholders globally available. As identifiers that start with an underscore are not allowed at the global namespace, and since defining a variable in a header would cause link errors, the placeholders have been put in an unnamed namespace.

Peter Dimov wrote:
I'm really not sure what do you mean by "modern" boost requirements.
None of the libraries that have recently been included into boost placed their headers in the boost root directory. I don't know whether this has become a (formal) requirement but that's what I wanted to express.
a) this header should be placed in the bind subdirectory, e.g. boost/bind/bind.hpp
What purpose does that serve? Why not boost/bind/bind/bind.hpp?
It was just an idea how to separate this header from the existing. One of many possible.
b) this header should introduce a separate namespace 'bind' or 'function' to avoid the well-known namespace clashes with boost::lambda that are _really_ annoying.
Again, what purpose would that serve? The only name that bind.hpp "reserves" in boost is 'bind'. Defining a namespace 'bind' still reserves the same name in boost, namely, 'bind', except that user code is now uglier.
Try to include boost/bind.hpp and boost/lambda/bind.hpp at the same time (just for matters of uniformity: this is the first time where I don't agree that one of those includes is in a subdirectory and the other is not!) I've not found any solution for how to use e.g. _1 from boost.lambda in one function and _1 from boost.bind in another _without_ having to qualify these two everytime, which is totally ugly IMO.
The original intent has been to make the placeholders globally available. As identifiers that start with an underscore are not allowed at the global namespace, and since defining a variable in a header would cause link errors, the placeholders have been put in an unnamed namespace.
ah ... I understand. IIRC, the _1 from boost.lamba are types and don't have these problems therefore. This means more or less that I'll never be able to write 'using boost::_1', no? Stefan

Stefan Slapeta wrote:
Peter Dimov wrote:
I'm really not sure what do you mean by "modern" boost requirements.
None of the libraries that have recently been included into boost placed their headers in the boost root directory. I don't know whether this has become a (formal) requirement but that's what I wanted to express.
a) this header should be placed in the bind subdirectory, e.g. boost/bind/bind.hpp
What purpose does that serve? Why not boost/bind/bind/bind.hpp?
It was just an idea how to separate this header from the existing. One of many possible.
Currently boost/ appears to contain 98 header files. Bringing this down to 97 wouldn't be much of an improvement.
b) this header should introduce a separate namespace 'bind' or 'function' to avoid the well-known namespace clashes with boost::lambda that are _really_ annoying.
Again, what purpose would that serve? The only name that bind.hpp "reserves" in boost is 'bind'. Defining a namespace 'bind' still reserves the same name in boost, namely, 'bind', except that user code is now uglier.
Try to include boost/bind.hpp and boost/lambda/bind.hpp at the same time (just for matters of uniformity: this is the first time where I don't agree that one of those includes is in a subdirectory and the other is not!) I've not found any solution for how to use e.g. _1 from boost.lambda in one function and _1 from boost.bind in another _without_ having to qualify these two everytime, which is totally ugly IMO.
You bring up the legitimate problem of bind's _1 clashing with lambda's _1 (when "using namespace boost::lambda" is in effect), but I totally don't see what this has to do with moving boost::bind to boost::bind::bind. To answer your specific question, ::_1 selects the Bind placeholder and boost::lambda::_1 selects Lambda's one; consequently, "using ::_1" is an using declaration for Bind's _1, and "using boost::lambda::_1" is the using declaration for its Lambda counterpart. I only tested them on VC 7.1, though; maybe your compiler doesn't accept them?
The original intent has been to make the placeholders globally available. As identifiers that start with an underscore are not allowed at the global namespace, and since defining a variable in a header would cause link errors, the placeholders have been put in an unnamed namespace.
ah ... I understand. IIRC, the _1 from boost.lamba are types and don't have these problems therefore.
No, Lambda's placeholders are variables in an unnamed namespace, too. MPL's placeholders are types. :-)
This means more or less that I'll never be able to write 'using boost::_1', no?
Probably not. You'll use "using namespace boost::placeholders" instead, when bind is modified to conform a bit more closely to TR1. The problem is that this breaks existing code. Of course when you have two using directives, one for Bind and one for Lambda, _1 will once again become ambiguous.

Peter Dimov wrote:
Currently boost/ appears to contain 98 header files. Bringing this down to 97 wouldn't be much of an improvement.
I didn't propose to delete the old one.
You bring up the legitimate problem of bind's _1 clashing with lambda's _1 (when "using namespace boost::lambda" is in effect), but I totally don't see what this has to do with moving boost::bind to boost::bind::bind.
Symmetry: boost::lambda::bind, boost::bind::bind (or maybe boost::function::bind and also include boost.function library there)
To answer your specific question, ::_1 selects the Bind placeholder and boost::lambda::_1 selects Lambda's one; consequently, "using ::_1" is an using declaration for Bind's _1, and "using boost::lambda::_1" is the using declaration for its Lambda counterpart. I only tested them on VC 7.1, though; maybe your compiler doesn't accept them?
This might be a different discussion but I simply don't understand what are the rules for putting boost.bind and boost.function in the 'global' boost namespace and many other libraries not. Historical reasons? A matter of interface size? [...]
Probably not. You'll use "using namespace boost::placeholders" instead, when bind is modified to conform a bit more closely to TR1. The problem is that this breaks existing code. Of course when you have two using directives, one for Bind and one for Lambda, _1 will once again become ambiguous.
There will be other headers for the TR1 implementations, so breaking existing code is not so much my problem. Stefan

Stefan Slapeta wrote:
This might be a different discussion but I simply don't understand what are the rules for putting boost.bind and boost.function in the 'global' boost namespace and many other libraries not. Historical reasons? A matter of interface size?
boost::bind is one identifier. boost::function is one identifier. It doesn't make much sense to put one identifier in its own subnamespace.

Peter, I've been expecting for some time that you were going to put the placeholders in a sub-namespace of boost, if only to avoid the ODR violations it is currently causing. No? The fact that I have to write mpl::_1 just to avoid colliding with <unnamed>::_1 is disconcerting at best. If another library came along and did what boost/bind/placeholders.hpp does, it would cause a clash. My suggestion, assuming you care about backwards compatibility, is: boost/bind/placeholders.hpp declares placeholders in namespace boost::bind::placeholders. boost/bind/bind.hpp has the current contents of boost/bind.hpp, except that placeholders are not declared in the <unnamed>:: boost/bind.hpp #include <boost/bind/bind.hpp> #include <boost/bind/placeholders.hpp> namespace { using namespace boost::bind::placeholders; } Is something wrong with that? -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

David Abrahams wrote:
boost/bind/bind.hpp
has the current contents of boost/bind.hpp, except that placeholders are not declared in the <unnamed>::
Nevertheless, please think about putting bind itself (and maybe the rest) into namespace boost::bind as well, if only to introduce some kind of symmetry between bind and lambda!
boost/bind.hpp
#include <boost/bind/bind.hpp> #include <boost/bind/placeholders.hpp> namespace { using namespace boost::bind::placeholders; }
Is something wrong with that?
_PLEASE_ can we have this? Stefan

David Abrahams wrote:
Peter, I've been expecting for some time that you were going to put the placeholders in a sub-namespace of boost, if only to avoid the ODR violations it is currently causing. No?
Correct me if I'm wrong, but the ODR violations are caused by the use of an unnamed namespace; this is not related to whether the placeholders are in a subnamespace of boost. It seems to me that Lambda's placeholders should be susceptible to the same sort of ODR violations. (I know that I asked you for an ODR/_1 example once and you provided it, but I don't remember what it was and can't find it at the moment. Sorry.)
The fact that I have to write mpl::_1 just to avoid colliding with <unnamed>::_1 is disconcerting at best. If another library came along and did what boost/bind/placeholders.hpp does, it would cause a clash.
First mover advantage, you know. (Kidding.)
My suggestion, assuming you care about backwards compatibility, is:
boost/bind/placeholders.hpp
declares placeholders in namespace boost::bind::placeholders.
But does not _define_ them? (I had boost::placeholders in mind for a namespace, consistent with std::tr1::placeholders; when you use 'boost' as a substitute for 'std::tr1', boost::bind::placeholders won't work.)
boost/bind/bind.hpp
has the current contents of boost/bind.hpp, except that placeholders are not declared in the <unnamed>::
boost/bind.hpp
#include <boost/bind/bind.hpp> #include <boost/bind/placeholders.hpp> namespace { using namespace boost::bind::placeholders; }
Hm. What is the difference between this directive and the simple using namespace boost::bind::placeholders; ? I can't think of any. This, of course, will still require you to use mpl::_1. I assume that you intend to fix all your includes to belong to... err, point to the using-directive-less version?

Peter Dimov wrote:
David Abrahams wrote:
boost/bind.hpp
#include <boost/bind/bind.hpp> #include <boost/bind/placeholders.hpp> namespace { using namespace boost::bind::placeholders; }
This, of course, will still require you to use mpl::_1. I assume that you intend to fix all your includes to belong to... err, point to the using-directive-less version?
And to expand on that, you surely realize that this won't help either, because the user can #include <boost/bind.hpp> before your header and reintroduce the ambiguity?

Peter Dimov wrote:
Peter Dimov wrote:
David Abrahams wrote:
boost/bind.hpp
#include <boost/bind/bind.hpp> #include <boost/bind/placeholders.hpp> namespace { using namespace boost::bind::placeholders; }
This, of course, will still require you to use mpl::_1. I assume that you intend to fix all your includes to belong to... err, point to the using-directive-less version?
And to expand on that, you surely realize that this won't help either, because the user can #include <boost/bind.hpp> before your header and reintroduce the ambiguity?
It won't prevent me from having to use qualification or local "using." It will help because I won't be forcing the ambiguity problem on the user just by dint of #including a boost header. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

Peter Dimov wrote:
David Abrahams wrote:
Peter, I've been expecting for some time that you were going to put the placeholders in a sub-namespace of boost, if only to avoid the ODR violations it is currently causing. No?
Correct me if I'm wrong, but the ODR violations are caused by the use of an unnamed namespace;
True.
this is not related to whether the placeholders are in a subnamespace of boost.
True again. That's a separate issue; anything we put outside boost is subject to unresolvable conflicts. <unnamed>:: is especially vulnerable.
It seems to me that Lambda's placeholders should be susceptible to the same sort of ODR violations.
I don't know what lambda does. I know mpl doesn't do that.
(I know that I asked you for an ODR/_1 example once and you provided it, but I don't remember what it was and can't find it at the moment. Sorry.)
int x(int); template <class T> void f() { boost::bind(x, _1); } Now all you need is for two translation units to instantiate f<X> for some X, the same in each TU.
The fact that I have to write mpl::_1 just to avoid colliding with <unnamed>::_1 is disconcerting at best. If another library came along and did what boost/bind/placeholders.hpp does, it would cause a clash.
First mover advantage, you know. (Kidding.)
My suggestion, assuming you care about backwards compatibility, is:
boost/bind/placeholders.hpp
declares placeholders in namespace boost::bind::placeholders.
But does not _define_ them?
You could define them as constants. Maybe enums would work: enum _1t { _1 }; enum _2t { _2 }; ??
(I had boost::placeholders in mind for a namespace, consistent with std::tr1::placeholders; when you use 'boost' as a substitute for 'std::tr1', boost::bind::placeholders won't work.)
Okay, as long as you cooperate with phoenix and lambda, as far as I'm concerned.
boost/bind/bind.hpp
has the current contents of boost/bind.hpp, except that placeholders are not declared in the <unnamed>::
boost/bind.hpp
#include <boost/bind/bind.hpp> #include <boost/bind/placeholders.hpp> namespace { using namespace boost::bind::placeholders; }
Hm. What is the difference between this directive and the simple
using namespace boost::bind::placeholders;
? I can't think of any.
Honestly, I'm not sure there is any.
This, of course, will still require you to use mpl::_1.
Yes, I expect that. Anyone conscientious will have to use qualification or local using directives to access placeholders.
I assume that you intend to fix all your includes to belong to... err, point to the using-directive-less version?
You bet. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

David Abrahams wrote:
Peter Dimov wrote:
(I had boost::placeholders in mind for a namespace, consistent with std::tr1::placeholders; when you use 'boost' as a substitute for 'std::tr1', boost::bind::placeholders won't work.)
Okay, as long as you cooperate with phoenix and lambda, as far as I'm concerned.
What specific kind of cooperation do you have in mind?

Peter Dimov wrote:
David Abrahams wrote:
Peter Dimov wrote:
(I had boost::placeholders in mind for a namespace, consistent with std::tr1::placeholders; when you use 'boost' as a substitute for 'std::tr1', boost::bind::placeholders won't work.)
Okay, as long as you cooperate with phoenix and lambda, as far as I'm concerned.
What specific kind of cooperation do you have in mind?
Ideally? You all use the same placeholders. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

On Nov 30, 2004, at 7:52 AM, David Abrahams wrote:
Peter Dimov wrote:
David Abrahams wrote:
Peter Dimov wrote:
(I had boost::placeholders in mind for a namespace, consistent with std::tr1::placeholders; when you use 'boost' as a substitute for 'std::tr1', boost::bind::placeholders won't work.)
Okay, as long as you cooperate with phoenix and lambda, as far as I'm concerned. What specific kind of cooperation do you have in mind?
Ideally? You all use the same placeholders.
I've also wondered if a general "placeholder library" is possible. -Howard

Howard Hinnant wrote:
I've also wondered if a general "placeholder library" is possible.
Thanks Howard! I didn't dare to ask myself. However, I'm wondering if the placeholders as specified in TR1 can be used by mpl?!?! Stefan

Stefan Slapeta wrote:
Howard Hinnant wrote:
I've also wondered if a general "placeholder library" is possible.
Thanks Howard! I didn't dare to ask myself.
However, I'm wondering if the placeholders as specified in TR1 can be used by mpl?!?!
The placeholders specified in TR1 are _values_. MPL uses _types_.

Howard Hinnant wrote:
On Nov 30, 2004, at 7:52 AM, David Abrahams wrote:
Peter Dimov wrote:
David Abrahams wrote:
Peter Dimov wrote:
(I had boost::placeholders in mind for a namespace, consistent with std::tr1::placeholders; when you use 'boost' as a substitute for 'std::tr1', boost::bind::placeholders won't work.)
Okay, as long as you cooperate with phoenix and lambda, as far as I'm concerned. What specific kind of cooperation do you have in mind?
Ideally? You all use the same placeholders.
I've also wondered if a general "placeholder library" is possible.
It's possible to write libraries so that they recognize the same placeholders, but the existing Bind and Lambda codebases aren't written in such a way. However I'd expect Metrowerks's implementation to be able to use Bind's and Lambda's placeholders; the only thing that is needed is appropriate specializations of std::tr1::is_placeholder. By specializing std::tr1::is_bind_expression for boost::_bi::bind_t<R, F, L>, std::tr1::bind should even be able to recognize a nested boost::bind subexpression. Daniel Wallin's suggestion of using #define _1 arg<1>() which is both a type and a value can enable even type (mpl) and value (bind, lambda) placeholders to be unified. Of course I can only imagine what the response to a macro _1 would be from an audience that can't even stand a global _1.

David Abrahams wrote:
Peter Dimov wrote:
David Abrahams wrote:
Peter Dimov wrote:
(I had boost::placeholders in mind for a namespace, consistent with std::tr1::placeholders; when you use 'boost' as a substitute for 'std::tr1', boost::bind::placeholders won't work.)
Okay, as long as you cooperate with phoenix and lambda, as far as I'm concerned.
What specific kind of cooperation do you have in mind?
Ideally? You all use the same placeholders.
Ideally, yes. In practice, this can't happen, not with the current implementations of Bind and Lambda. I don't know about Phoenix, but it doesn't use _1 anyway. The problem on Boost.Bind's side is that it recognizes placeholders by their exact type, rather than using an is_placeholder metafunction, as specified in TR1. So it can only work with its own placeholders. The problem on Lambda's side is that Lambda's placeholders aren't really placeholders, but full-featured Lambda functors. Lambda doesn't use an is_placeholder metafunction either. In principle, Bind can use Lambda functors as placeholders, but getting around the ODR problem would require Borland's version of placeholders (inline functions named _k) to be used on all compilers in Bind, and such an inline function can't be a Lambda functor. In addition, Bind's placeholders are assignable. This allows Bind's function objects to be assignable as well. In Lambda, _1 = _1 is not an assignment, but a lambda expression. The framework outlined in TR1 - is_placeholder and is_bind_expression - allows two implementations of tr1::bind to recognize each other's placeholders and subexpressions, so that you can mix and match lib1::bind, lib2::bind, lib1::_1 and lib2::_2 in the same bind expression. Unfortunately, neither Boost.Bind nor Boost.Lambda honor this framework, and there are objective reasons for both to not change to accommodate it. (In Bind's case, support for older compilers.)

Peter Dimov wrote:
The framework outlined in TR1 - is_placeholder and is_bind_expression - allows two implementations of tr1::bind to recognize each other's placeholders and subexpressions, so that you can mix and match lib1::bind, lib2::bind, lib1::_1 and lib2::_2 in the same bind expression. Unfortunately, neither Boost.Bind nor Boost.Lambda honor this framework, and there are objective reasons for both to not change to accommodate it. (In Bind's case, support for older compilers.)
Well, lambda is going to be undergoing an integration with Phoenix, which leaves ample room for flexibility on that end. -- Dave Abrahams Boost Consulting http://www.boost-consulting.com

Peter Dimov wrote:
[many things]
Thanks for the detailed explanation.
The problem on Boost.Bind's side is that it recognizes placeholders by their exact type, rather than using an is_placeholder metafunction, as specified in TR1. So it can only work with its own placeholders.
A naive question: Is this something that _could_ be changed without changing the library interface or not? Stefan
participants (5)
-
David Abrahams
-
Howard Hinnant
-
Peter Dimov
-
Stefan Slapeta
-
Stefan Slapeta