Ru-Brd |
To illustrate the overall effect achieved by our sophisticated treatment of functor composition and value binding, we provide here a complete implementation of these operations for functors with up to three parameters. (It is straightforward to extend this to a dozen parameters or so, but we prefer to keep the printed code relatively concise .) Let's first look at some sample client code: // functors/functorops.cpp #include <iostream> #include <string> #include <typeinfo> #include "functorops.hpp" bool compare (std::string debugstr, double v1, float v2) { if (debugstr != "") { std::cout << debugstr << ": " << v1 << (v1<v2? '<' : '>') << v2 << '\n'; } return v1<v2; } void print_name_value (std::string name, double value) { std::cout << name << ": " << value << '\n'; } double sub (double a, double b) { return a-b; } double twice (double a) { return 2*a; } int main() { using std::cout; // demonstrate composition: cout << "Composition result: " << compose(func_ptr(sub), func_ptr(twice))(3.0, 7.0) << '\n'; // demonstrate binding: cout << "Binding result: " << bindfp<1>(compare, "main()->compare()")(1.02, 1.03) << '\n'; cout << "Binding output: "; bindfp<1>(print_name_value, "the ultimate answer to life")(42); // combine composition and binding: cout << "Mixing composition and binding (bind<1>): " << bind<1>(compose(func_ptr(sub),func_ptr(twice)), 7.0)(3.0) << '\n'; cout << "Mixing composition and binding (bind<2>): " << bind<2>(compose(func_ptr(sub),func_ptr(twice)), 7.0)(3.0) << '\n'; } The program has the following output: Composition result: -8 Binding result: main()->compare(): 1.02<1.03 1 Binding output: the ultimate answer to life: 42 Mixing composition and binding (bind<1>): 8 Mixing composition and binding (bind<2>): -8 The main conclusion that can be drawn from this little program is that using the functor operations developed in this section is very simple (even though implementing them was no easy task). Note also how the binding and the composing templates interoperate seemlessly. The core facility that enables this is the small set of conventions we established for functors in Section 22.6.1 on page 436. This is not unlike the requirements established for iterators in the C++ standard library. Functors that do not follow our conventions are easily wrapped in adapter classes (as illustrated by our func_ptr() adaptation templates). Furthermore, our design allows state-of-the-art compilers to avoid any unnecessary run-time penalty compared to hand-coded functors. Finally, the contents of functorops.hpp , which shows which header files are necessary to be able to compile the previous example, looks as follows : // functors/functorops.hpp #ifndef FUNCTOROPS_HPP #define FUNCTOROPS_HPP // define func_ptr() , FunctionPtr , and FunctionPtrT #include "funcptr.hpp" // define Composer<> #include "compose6.hpp" // define convenience function compose() #include "composeconv.hpp" // define Binder<> // - includes boundval.hpp to define BoundVal<> and StaticBoundVal<> // - includes forwardparam.hpp to define ForwardParamT<> // - includes functorparam.hpp to define FunctorParam<> // - includes binderparams.hpp to define BinderParams<> // - includes signselect.hpp to define SignSelectT<> #include "binder5.hpp" // define convenience functions bind() and bindfp() #include "bindconv.hpp" #include "bindfp1.hpp" #include "bindfp2.hpp" #include "bindfp3.hpp" #endif // FUNCTOROPS_HPP |
Ru-Brd |