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:
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 acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk