// Call Wrappers template <class T> class matrix { public: matrix( int i, int j ); matrix( const matrix &other); ~matrix(); matrix& operator=( const matrix &other); int rows() const { return x; } int cols() const { return y; } T& at( int i, int j) throw(indexError); const T& at( int i, int j) const throw(indexError); T& operator()( int i, int j); const T& operator()( int i, int j) const; private: int x; int y; T *v; void copy( const matrix &other); void check( int i, int j) const throw(indexError); }; // Functor: class with function call operator // Function pointers are callable types too. // // Tr1 introduces 4 new class templates to create Functors // #include <functional> reference_wrapper function mem_fn bind ref cref result_of // Terminology Callable_type: - pointer to function - pointer to member function - pointer to member data - objects left to a function call Examples: double (*fptr)(double); // pointer to function int (date::*getter)() const; // pointer to member function int date::*field; // pointer to member data class C // function call operator { public: void operator()(int i); }; fptr = sin; getter = &date::get_year; field = &date::year; C c; fptr(0.5) <==> (*fptr)(0.5) (obj.*getter)() ((*ptr).*getter)() <==> (ptr->*getter)() c.operator() <==> c() #include <iostream> #include <math.h> using std::cout; class wrapper // simple call wrapper type { typedef float(*fp)(float); public: wrapper(fp ptr) : fptr(ptr) {} float operator()(float arg) // call operation; forwards to target object { return fptr(arg); } private: fp fptr; // target object }; int main() // demonstrate use of call wrapper { wrapper wrap(cosf); // call wrapper cout << "cosf(1.0) is " << cosf(1.0) << '\n'; cout << "wrap(1.0) is " << wrap(1.0) << '\n'; return 0; }; // A call wrapper can be copy constructed // INVOKE INVOKE( fn, t1, t2, ... , tN) (t1.*fn)(t2, ... , tN) // pointer to member function ((*t1).*fn)(t2, ... , tN) // pointer to member function t1.*fn // pointer to member data (*t1).*fn // pointer to member data fn( t1, t2, ... , tN) // otherwise INVOKE_R( fn, t1, t2, ... , tN, Ret) // INVOKE() converts to Ret struct base { void f(); int g(double); int h(double, double); }; struct derived : base { }; base b; derived d; base& br = d; INVOKE( &base::f, b) (b.*f)() INVOKE( &base::g, d, 1.0) (d.*f)(1.0) INVOKE( &base::h, br, 1.0, 2.0) (br.*f)(1.0, 2.0) derived *dp = new derived; base *bp = dp; shared_ptr<base> sp(bp); INVOKE( &base::f, bp) ((*bp).*f)() INVOKE( &base::g, dp, 1.0) ((*dp).*f)(1.0) INVOKE( &base::h, sp, 1.0, 2.0) ((*sp).*f)(1.0, 2.0) void func(base&); struct fun_obj { void operator()() const; bool operator()(int) const; }; fun_obj obj; INVOKE( func, d) func(d) INVOKE( obj) obj() INVOKE( obj, 3) obj(3) #include <functional> #include <math.h> #include <iostream> #include <typeinfo> using std::tr1::result_of; using std::ostream; using std::cout; class C { // sample class public: C(int i0) : i(i0) {} long get() const { return i; } int i; void operator()(int ii) { i = ii; } typedef void result_type; }; template <class Fty, class Arg> void show_return(Fty fun, Arg arg) { // show return type of fun(arg) typedef typename result_of<Fty(Arg)>::type ret; cout << "Return type of " << typeid(Fty).name() << " when called with " << typeid(Arg).name() << " is " << typeid(ret).name() << '\n'; } int main() { // demonstrate class template result_of C c(1); C *cp = &c; const C *ccp = &c; show_return(cosf, 1.0); // cosf(float) returns float show_return(&C::get, cp); // C::get() returns long show_return(&C::i, ccp); // C::i has type const int show_return(c, 3); // C() returns void return 0; } // mem_fn template <class Ret, class T> XXXX mem_fn(Ret T::*pm); returns a simple call wrapper cw, where cw(a1, a2, ... , aN) <==> INVOKE(pm, a1, a2, ... , aN) XXXX : std::unary_function<T*, Ret> --> typedef Ret result_type --> typedef T* argument_type #include <functional> #include <memory> #include <iostream> using std::tr1::mem_fn; using std::tr1::shared_ptr; using std::cout; class C { // simple class with member function public: C(int i0 = 0) : i(i0) {} void show() const { // show contents cout << i << '\n'; } private: int i; }; template <class Fty, class Ty> void apply(Fty fn, Ty obj) { // call a function object with one argument fn(obj); } int main() { // demonstrate simple use of mem_fn C c0(0); C *cp = new C(1); shared_ptr<C> sp(new C(2)); void (C::*mptr)() const = &C::show; apply(mem_fn(mptr), c0); // equivalent to (c0.*mptr)() apply(mem_fn(mptr), cp); // equivalent to (cp->*mptr)() apply(mem_fn(mptr), sp); // equivalent to ((*sp).*mptr)() delete cp; return 0; } #include <functional> #include <iostream> using std::tr1::mem_fn; using std::cout; class C { // simple class with member functions public: C(int i0 = 0) : i(i0) {} void show() const { // show contents cout << "in show: " << i << '\n'; } void one_arg(int j) const { // member function taking one argument cout << "in one_arg: " << i << ", " << j << '\n'; } void two_args(int j, int k) const { // member function taking two arguments cout << "in two_args: " << i << ", " << j << ", " << k << '\n'; } private: int i; }; int main() { C c(1); int two = 2; int three = 3; mem_fn(&C::show)(c); // c.show(); mem_fn(&C::one_arg)(c, two); // c.one_arg(two); mem_fn(&C::two_args)(c, two, three);// c.two_args(two, three); return 0; } // reference_wrapper // creates objects acting like referencies // but could be copied #include <functional> using std::tr1::reference_wrapper; class ref { // simple class containing reference public: ref(int& i) : member(i) {} private: int& member; }; class refwrap { // simple class containing reference_wrapper public: refwrap(int& i) : member(i) {} private: reference_wrapper<int> member; }; void f() { // demonstrate copying int i, j; ref r0(i); ref r1(j); r1 = r0; // error: ref can't be copied refwrap rw0(i); refwrap rw1(j); rw1 = rw0; // okay: refwrap can be copied } #include <functional> #include <iostream> using std::tr1::reference_wrapper; using std::cout; int main() { // demonstrate basic use of reference_wrapper int Stuhldreher = 3; reference_wrapper<int> rw(Stuhldreher); cout << rw << '\n'; // displays value of Stuhldreher Stuhldreher = 4; cout << rw << '\n'; // displays new value of Stuhldreher rw.get() = 5; // changes value of Stuhldreher cout << Stuhldreher << '\n'; // displays new value return 0; } #include <functional> #include <iostream> using std::tr1::reference_wrapper; using std::tr1::ref; using std::tr1::cref; using std::cout; void show(int& i) { // show value referred to by reference to int cout << "int&: " << i << '\n'; } void show(const int& i) { // show value referred to by reference to const int cout << "const int&: " << i << '\n'; } int main() { // demonstrate use of ref and cref int Miller = 3; show(ref(Miller)); // calls show(int&); reference_wrapper<int> rw0(Miller); show(ref(rw0)); // calls show(int&); show(cref(Miller)); // calls show(const int&); reference_wrapper<const int> rw1(Miller); show(cref(rw1)); // calls show(const int&); return 0; } #include <functional> #include <iostream> using std::tr1::reference_wrapper; using std::cout; struct base { // base class virtual void show() const { // show name of base class cout << "base\n"; } }; struct derived0 : base { // one derived class void show() const { // show name of derived class cout << "derived0\n"; } }; struct derived1 : base { // another derived class void show() const { // show name of derived class cout << "derived1\n"; } }; int main() { // demonstrate reference_wrapper's support for polymorphism derived0 Crowley; derived1 Layden; reference_wrapper<base> rw0(Crowley); rw0.get().show(); // calls derived0::show reference_wrapper<base> rw1(Layden); rw1.get().show(); // calls derived1::show return 0; } #include <functional> #include <iostream> using std::tr1::reference_wrapper; using std::tr1::cref; using std::cout; void hello() { // simple function cout << "Hello, world\n"; } void goodbye() { // another simple function cout << "Goodbye, cruel world\n"; } int main() { // demonstrate invocation of reference_wrapper object typedef void (*const fun)(); reference_wrapper<fun> rw(&hello); rw(); // calls hello rw = cref(&goodbye); rw(); // calls goodbye return 0; } // function