// 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