Joaquín Mª López Muñoz wrote:
Hello,
The non-documented BOOST_BIND_NO_PLACEHOLDERS macro suppresses the definition of (anonymous namespace)::_1, (anonymous namespace)::_2, etc., presumably to cope with potential clashes with other libs' placeholders such as Boost.Lambda's when in the presence of using directives.
I think that the presumption is incorrect. If my memory serves, the intent of BOOST_BIND_NO_PLACEHOLDERS was not to cope with _1 clashes, but with various other problems caused by their definitions, such as, for instance, not working with precompiled headers, code bloat caused by their repeat definition in every translation unit, and so on. So people who would rather not modify their Boost installation were able to (globally, at project level) suppress the definitions and add their own. If you were looking at the macro as a way to enable a library header to avoid _1 collisions, it will not work. User code which includes both your library header and then boost/bind.hpp and tries to use _1 will break, as the second inclusion of bind.hpp will do nothing and the placeholders will remain undefined.
The problem with this is that using Boost.Bind without placeholder names requires writing code such as
bind(f,boost::arg<1>(),boost::arg<2>());
but boost::arg<> is not documented!! (in fact, Boost.Bind synopsis explicitly defines _1, _2 etc. as having undocumented types unspecified-placeholder-type-1, unspecified-placeholder-type-2 and so on).
The synopsis is correct - the placeholders are currently not of type arg<I> half of the time, depending on the compiler; arg<I>(*)() is used instead. arg<I> always works as a placeholder though.
Maybe Boost.Bind documentation can be changed so that BOOST_BIND_NO_PLACEHOLDERS and boost::arg<> are documented?
I'm a bit reluctant to do that. The macro, in particular, will likely go away once the placeholders finally move to a namespace. boost::arg<> will probably work for all eternity, but there is a documented way to define placeholders, as Steven notes.