[libstdc++ PATH] tr1::bind support

Douglas Gregor doug.gregor@gmail.com
Sun Mar 20 21:12:00 GMT 2005


Hello,

The attached patch introduces support for tr1::bind for libstdc++-v3 (section 
3.6 of TR1). Tested against i686-pc-linux-gnu, no regressions. This 
particular patch is against the main trunk (4.1.0), but I would like to 
commit to both the main trunk and the 4.0 branch. ChangeLog follows.

Details for those that wish to review the internals:

First of all, there's a lot of preprocessor magic going on here. In addition 
to functional_iterate.h (the repetition header for functional), there is also 
a mu_iterate.h and bind_iterate.h. bind_iterate.h is the most interesting 
because it's included 20 times from inside functional_iterate.h, using a 
different repetition header (bind_repeat.h) and a different set of variables. 
Reviewing can be made a LOT easier by looking at the preprocessed output and 
focusing on some small number of parameters only. Now, on to the fun part:

Class template _Mu implements the "mu" function used in the original bind 
proposal, which corresponds to 3.6.3/5 in TR1 and is responsible for 
evaluating bound arguments when calling a bind() function object. Consider 
the following code:

  int x = 17;
  bind(std::plus<int>(), 5, _1)(x);

The call to bind() returns a function object (of type _Bind<...>), which is 
then called with the value "x". That evaluation calls std::plus<int>()(v1, 
v2). "mu" is responsible for turning 5 into v1 and _1 into x. (The result of 
the overally expression is 22). _Mu needs to deal with four cases 
(corresponding to the four bullets in TR1 3.6.3/5), each of which is handled 
by a partial specialization of _Mu in the functional header. _Mu has two 
interesting properties:
  1) It is a function object (with enough smarts to work with result_of), but 
always takes two parameters: a reference to the bound argument and a tuple of 
the arguments that were passed to bind. We use a tuple so that we require 
less repetition. However, it also means that we're limited to passing 10 
arguments to bind() because tuple<> accepts at most 10 parameters. See 
workarounds in, e.g., mu_iterate.h.
  2) Bullet 2 handles nested bind expressions, which require that the tuple be 
explicitly "unpacked" into several arguments before calling the underlying 
bind expression. Thus, unfortunately, means that we need to have many 
operator() overloads, provided by mu_iterate.h.

The actual bind() overloads and the _Bind/_Bind_result function objects 
returned by _Bind aren't as interested as one would expect. They are defined 
based on the number of bound parameters (i.e., the number of parameters 
passed to bind(...)), in functional_iterate.h. The _Bind version has a weak 
result type, whereas the _Bind_result version matches calls to bind<R>(), 
where R is the specified return type. Each _Bind/_Bind_result object has lots 
of operator() overloads, because the function objects returned by bind can 
take any number of parameters. Thus, the operator()'s are defined in 
bind_iterate.h, included through bind_repeat.h. Note that these operator()'s 
use _Mu to map the values to be passed on to the bound function object, both 
for return type deduction (based on result_of, of course) and for building 
the actual arguments.

If there are any questions, I'll answer them as best I can. The code makes the 
most sense when reading along with TR1 3.6 and/or the original bind() 
proposal.

 Doug

2005-03-20  Douglas Gregor  <doug.gregor@gmail.com>

 * include/Makefile.am (tr1_headers): Add bind and mu repetition
 headers and reference_wrapper<> forwarding header.
 * include/Makefile.in: Regenerate.
 * include/tr1/bind_iterate.h: Implementation of function call
 operators for the function object returned from tr1::bind().
 * include/tr1/bind_repeat.h: Bind-specific repetition header,
 akin to include/tr1/repeat.h. 
 * include/tr1/functional (_Mem_fn): Bug fix: declare result member
 template for use with result_of.
 (is_bind_expression): New.
 (is_placeholder): New.
 (_Placeholder): New. Placeholder type for bind.
 (_Mu): New. Implementation detail of bind.
 (_Bind, _Bind_result): New. Function objects returned by bind.
 (_GLIBCXX_JOIN): New. Required to create bind placeholders.
 * include/tr1/functional_iterate.h (_Bind, _Bind_result, bind):
 New. Implementation of tr1::bind.
 * include/tr1/mu_iterate.h (_Mu): result template and operator()
 for the _Mu helper to bind.
 * include/tr1/ref_fwd.h (reference_wrapper): Forward declaration
 used by tuple header.
 (ref): Ditto.
 (cref): Ditto.
 * include/tr1/repeat.h: Add bind-specific repetition macros.
 * include/tr1/tuple: Use reference_wrapper forwarding header for
 initial definitions, then include <tr1/functional> at the end, to
 make the circular dependencies work.
 (tie): Support zero-argument tie() function.
 * testsuite/testsuite_tr1.h: Remove extraneous semicolon.
 * testsuite/tr1/3_function_objects/bind/all_bound.cc: New test of
 bind() functionality with parameters bound.
 * testsuite/tr1/3_function_objects/bind/nested.cc: New test of
 nested bind() expressions.
 * testsuite/tr1/3_function_objects/bind/placeholders.cc: New test
 of bind() placeholders.
 * testsuite/tr1/3_function_objects/bind/ref.cc: New test of bind()
 with arguments bound via reference_wrapper<>.

-------------- next part --------------
A non-text attachment was scrubbed...
Name: bind-4.1.0.patch
Type: text/x-diff
Size: 119521 bytes
Desc: not available
URL: <http://gcc.gnu.org/pipermail/libstdc++/attachments/20050320/462d84b7/attachment.bin>


More information about the Libstdc++ mailing list