Overview
The function wrapper classes provide alternative to function pointers. It's basically a general-purpose polymorphic function wrapper.
Details
The function wrapper classes provide alternative to function pointers. It's basically a general-purpose polymorphic function wrapper. Instances of function classes can store, copy, and invoke function pointers, lambda expressions, bind expressions, or other function objects, as well as pointers to member functions and pointers to data members.
The syntax is as shown below:
//generic type. //defined for specialization template< typename T> class function; /* undefined */ //R return type //Args arguments template< typename Ret, class... Args > class function<R(Args...)>;
A decay copy of the wrapped callable object is stored internally by the object, which becomes the function's target member. The specific type of this target callable object is not needed in order to instantiate the function wrapper class; only its call signature.
function class objects can also be in a state with no target callable object. In this case they are known as empty functions, and calling them throws a bad_function_call exception.
constructors
Allocator based constructors are also available.
Name | Description |
---|---|
function() function (nullptr_t fn) | Default constructor with no target |
function (const function & fn) | Copy constructor. Copies target from fn to this. |
function (Fn fn) | The object stores a decayed copy of fn as its target. |
Example int square_fn(int x) {return x*x;} // a function object class: struct square_functor { int operator()(int x) {return x*x;} }; // a class with data members: struct square_struct { int x; int square() {return x*x;} }; //function function<int(int)> fn = square_fn; //returns 16 fn(4); //pointer to function function<int(int)> fnptr = &square_fn; //returns 16 fnptr(4); //function object function<int(int)> fnobj = square_functor(); //returns 16 fnobj(4); // lambda expression function<int(int)> fnlamb = [](int x){return x*x;}; //returns 16 fnlamb(4); //predefined function object function<int(int,int)> fnmul = multiplies<int>(); //returns 16 fnlamb(4); // pointer to data member function<int&(square_struct&)> value = &square_struct::x; // pointer to member function function<int(square_struct&)> sqr = &square_struct::square; square_struct t {}; //t.x=4 value(t)=4; //returns 16 sqr(t); |
methods
Name | Description |
---|---|
operator bool() | Returns whether the object is callable.i.e., if it has a callable object as target. Example function<int(int,int)> fnmul; bool b = static_cast<bool>(fnmul); fnmul = multiplies<int>(); b = static_cast<bool>(fnmul); |
Ret operator() (Args... args) | Calls the target callable object, forwarding args as arguments. The effect depends on the type of the callable object targeted by the function object: If the target is a function pointer or a function object, it is called forwarding the arguments to the call. If the target is a pointer to a non-static member function, it is called using the first argument as the object on which the member is called (this may either be an object, a reference, or a pointer to it), and the remaining arguments are forwarded as arguments for the member function. If it is a pointer to a non-static data member, it should be called with a single argument, and the function returns a reference to that member of its argument (the argument may either be an object, a reference, or a pointer to it). If the object has no target (it is an empty function), it throws a bad_function_call exception. Example struct mul_struct { int x; int mul(int y) {return x*y;} }; square_struct a{10}; function<int(square_struct&)> fnx = &square_struct::x; function<int(square_struct&,int)> fnmul = &square_struct::mul; //prints 10 cout << fnx(a); //prints 100 cout << fnmul(a,10); |
TargetType* target() | Returns a pointer to the callable object stored in the function object. Because function is a polymorphic wrapper class, it is unaware of the static type of its target callable object, and thus the template parameter TargetType must be explicitly specified. TargetType shall match the target type, so that typeid(TargetType)==target_type(). Otherwise, the function always returns a null pointer. Example int add(int a, int b){return a+b;} int sub(int a, int b){return a-b;} function<int(int,int)> f = &add; function<int(int,int)> f2 = plus<int>(); //returns 120 (*f.target<int(*)(int,int)>())(100,20) << endl; //returns 120 (*f2.target<plus<int>>())(100,20); *f.target<int(*)(int,int)>() = ⊂ //returns 80 f(100,20); |
const type_info& target_type() | Returns the type_info object that identifies the type of the target. Example function<int(int,int)> f = add; function<int(int,int)> f2 = &add; function<int(int,int)> f3 = plus<int>(); //int (__cdecl*)(int,int) cout << f.target_type().name() << endl; //int (__cdecl*)(int,int) cout << f2.target_type().name() << endl; //struct std::plus<int> cout << f3.target_type().name() << endl; |
placeholder namespace
This namespace defines an unspecified number of objects: _1, _2, _3,..._N, where _N is implementation specific upper limit.
syntax
namespace placeholders { extern /* unspecified */ _1; extern /* unspecified */ _2; //.... extern /* unspecified */ _N; }
These are used to specify placeholders in calls to function bind. When the function object returned by bind is called, an argument with placeholder::_1 is replaced by the first argument in the call, placeholder::_2 is replaced by the second argument in the call, and so on.
Example
void printnum(int n) {cout << n << endl;} auto pnum = bind(printnum,placeholders::_1); //prints 10 pnum(10);
is_placeholder class
is_placeholder trait class can be used to check if the argument is a placeholder type or not.
syntax
template< class T >struct is_placeholder;
If T is the type of a standard placeholder (_1, _2, _3, ...), then this template is derived from std::integral_constant<int, 1>, std::integral_constant<int, 2>, std::integral_constant<int, 3>, respectively.
If T is not a standard placeholder type, this template is derived from std::integral_constant<int, 0>.
bind uses is_placeholder to detect placeholders for unbound arguments.
Example
//prints 1 cout << is_placeholder<decltype(placeholders::_1)>::value << endl; //prints 2 cout << is_placeholder<decltype(placeholders::_2)>::value << endl; //prints 0 cout << is_placeholder<int>::value << endl;mem_fnFunction template mem_fn generates wrapper objects for pointers to members, which can store, copy, and invoke a pointer to member. Both references and pointers (including smart pointers) to an object can be used when invoking a mem_fn.syntax
template <class Ret, class T>/* unspecified */ mem_fn (Ret T::* pm);Examplestruct Msg { char buf[50]; void print(){cout << buf;}; } m; auto pbuf = mem_fn(&Msg::buf); char str[] = "hello, world!"; auto len = char_traits<char>::length(str); //sets m.buf to "hello, world" char_traits<char>::copy(pbuf(m),str,len); auto pprint = mem_fn(&Msg::print);//prints "hello, world"
pprint(m);The example 10 demonstrates its usage.bind
Returns a function object based on fn, but with its arguments bound to args.
syntax
template <class Fn, class... Args>/* unspecified */ bind (Fn&& fn, Args&&... args);template <class Ret, class Fn, class... Args>/* unspecified */ bind (Fn&& fn, Args&&... args);
- fn is a function object, pointer to function or pointer to member.
- args is a list of arguments. Each argument may either be bound to a value or be a placeholder or a reference wrapper or another bind expression. If bound to a value, calling the returned function object will always use that value as argument otherwise the value passed in the call will be forwarded at runtime.
- ret A function object that, when called, calls fn with its arguments bound to args.
Example
struct Msg { char buf[50]; void print(){cout << buf;}; } m; char str[] = "hello, world!"; auto len = char_traits<char>::length(str); //sets m.buf to "hello, world" auto pbuf = bind(&Msg::buf,placeholders::_1); char_traits<char>::copy(pbuf(m),str,len); //calls m.print(); //prints hello, world auto pprint = bind(&Msg::print,placeholders::_1); pprint(m);
No comments:
Post a Comment