Boost logo

Boost :

From: Peter Dimov (pdimov_at_[hidden])
Date: 2001-08-16 05:38:45

From: "Ross Smith" <ross.s_at_[hidden]>
> There's an example under "Using bind with function pointers" that I'm
> pretty sure contains a typo:
> > bind covers the functionality of std::bind2nd as well:
> >
> > std::bind2nd(std::ptr_fun(f), 5)(x); // f(5, x)
> > bind(f, 5, _2)(x); // f(5, x)
> Unless I've completely misunderstood the way the placeholders are
> supposed to work, the third argument in the last line should be _1.

Someone that actually reads the docs. :-) You are right, of course.

> Under "Using bind with member function pointers", I don't understand one
> of the examples:
> > bind(&X::f, &x, _1)(i); // (&x)->f(i)
> Is this meant to imply that a pointer passed where the object is
> expected will automatically be dereferenced when the function is called?

No, bind does not dereference pointers. The reason this works is that

bind(&X::f, &x, _1)

is actually a shortcut form for

bind<R>(mem_fun(&X::f), &x, _1)

and it's the function object returned from mem_fun that is able to handle a
pointer or a reference to X as a first argument.

> I really dislike the "_number" notation for placeholders. First, it
> doesn't stand out -- it looks too much like an ordinary integer
> argument. (This is particularly confusing in the examples in the
> documentation, where most of the arguments _are_ integers.) In addition
> to the visual confusion, this also means that they're only one very
> small typo away from a bug that could be very hard to track down.

Ironically, _1 has evolved from the more traditional 'boost::arg1' notation.

The "perfect" syntax for a bound function is:

f($2, $1)


f(%2, %1)

depending on what skool you're from. [Likewise $1 + $2 for lambda(x, y)(x +

The closest I was able to get in C++ was

bind(f, _2, _1).

In my experience, the _1 notation really stands out and is not easily
confused with either 1 or -1. In contrast,

bind(f, arg2, arg1)

is less readable for someone that's not "in the know" - arg1 and arg2 are
pretty ordinary identifiers; the person will lose several minutes looking
for the variables named argN.

> Second, leading underscores are dangerous. Practically everyone agrees
> on that.

In general, yes, they are dangerous. In this particular case I think we're
pretty safe, though. :-)

> That applies to the implementation as well; a quick look at bind.hpp
> revealed far too many leading underscores for my peace of mind. If they

You aren't supposed to look at implementation details. :-)

> were long names it wouldn't be quite so bad, but they include names like
> _bi and _int -- again, exactly the sort of thing that some idiot is

_int will change.

_bi, on the other hand, is an intentional compromise. I want a short name
for the implementation details namespace for two reasons: first, it makes
the code easier to read, and second, it makes the error messages easier to
read. The last part is quite important, since the errors generated by, for

bind(f, 5, _2)(x);

are pretty long even with the short _bi.

On the other hand, I can't simply use some short name since this goes into
boost::, and boost:: is already getting too crowded (boost::detail even more
so.) So I settled on _bi.

> likely to have used as a macro somewhere deep in the bowels of
> <windows.h> or <unistd.h>. Please, _please_ do something about this.

I'm willing to take the risk. Nobody is safe from macros (pascal, min,
Sleep.) Of course if someone does report a conflict, _bi will change.

Peter Dimov
Multi Media Ltd.

Boost list run by bdawes at, gregod at, cpdaniel at, john at