STL--Function Objects(一)

The Concept of Function Objects

    A function object, or functor, is an object that has operator () defined so that int the following example

FunctionObjectType fo;
//...
fo(...);

the expression fo() is a call of operator () for the function object fo instead of a call of the function fo().

So the function object define as follow:

Class X {
  public:
    //define "function call" operator:
    return-value operator() (arguments) const;
    //...
};

Now you can use objects of this class to behave like a function that you can call:

X fo;
...
//call operator () for function object fo
fo(arg1, arg2);  //equivalent to: fo.operator() (arg1, ar2);

    Function objects are more than functions, and they have some advantages:

  1. Function objects are "function with state". Object that behave like pointers are smart pointers.
  2. Each function object has its own type. Ordinary functions have different types only when their signatures differ. However, function objects can have different types even when their signatures are the same.
  3. Function objects are usually faster than ordinary functions.

     Suppose that you want to add a certain value to all elements of a collection. If you know the value you want to add at compile time, you could use an ordinary function.

    If you need different values that are known at compile time, you could use a template instead.

    If you process the value to add at runtime,things get complicated. With function objects, you can write a "smater" function that behaves in the desired way. Because it may have a state, the object can be initialized by the correct value.

 

#include <list>
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include "print.hpp"
using namespace std;


//function object that adds the value with which it is initialized
class AddValue {
private:
	int theValue;    //the value to add
	
public:
	//construct initializes the value toadd
	AddValue(int v)
	  :theValue(v)
	{
	}
	
	//the "function call" for the element adds the value
	void operator() (int& elem) const {
		elem += theValue;
	}
};


int main()
{
	list<int> coll;
	
	//insert elements from 1 to 9
	for(int i=1; i <= 9; ++i) {
		coll.push_back(i);
	}
	
	PRINT_ELEMENTS(coll, "initialized:  ");
	
	//add value 10 to each element
	for_each(coll.begin(), coll.end(), AddValue(10));
	PRINT_ELEMENTS(coll, "after adding 10:  ");
	
	//add value of first element to each element
	for_each(coll.begin(), coll.end(), AddValue(*coll.begin()));
	PRINT_ELEMENTS(coll, "after adding first element:  ");
	
	system("pause");
}


/*
 * output of program:
 *
 * initialized:  1 2 3 4 5 6 7 8 9
 * after adding 10:  11 12 13 14 15 16 17 18 19
 * after adding first element:  22 23 24 25 26 27 28 29 30
 *
 */

 

Predefined Function Objects

    The C++ standard library contains several predefined function objects that cover fundamental operations. By use them, you don't have to write your own function objects in several cases. A typical example is a function onject used  as a sorting criterion.

set<int, less<int>> coll;    //sort elements with <
set<int, greater<int>> coll; //sort elements with >

Another place to apply predefined function objects are algorithms. Consider the following example:

#include <deque>
#include <algorithm>
#include <functional>
#include <iostream>
#include <cstdlib>
#include "print.hpp"
using namespace std;

int main()
{
	deque<int> coll = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	PRINT_ELEMENTS(coll, "initialized: ");
	
	//negate all values in coll
	transform(coll.cbegin(), coll.cend(), coll.begin(), negate<int>());
	PRINT_ELEMENTS(coll, "negate: ");
	
	//square all vlaues in coll
	transform(coll.cbegin(), coll.cend(), coll.cbegin(), coll.begin(), multiplies<int>());
	PRINT_ELEMENTS(coll, "squared: ");
	
	system("pause");
}


/*
 * output of program:
 *
 * initialized: 1 2 3 4 5 6 7 8 9
 * negate: -1 -2 -3 -4 -5 -6 -7 -8 -9
 * squared: 1 4 9 16 25 36 49 64 81
 *
 */


// print.hpp

#include<iostream>
#include<string>

//PRINT_ELEMENTS()
// - prints optional string optstr followed by
// - all elements of the collection coll
// - in one line,separated by spaces
template <typename T>
inline void PRINT_ELEMENTS(const T& coll, const std::string& optstr="")
{
	std::cout << optstr;
	for(const auto& elem : coll) {
		std::cout << elem << ' ';
	}
	std::cout << std::endl;
}

The header for the predefined function objects is included <functional>

Then, two predefined function objects are used to negate and square the elements in coll.

 

Binders

    You can use special function adapters, or so-called binders, to combine predefined function objects with other values or use special cases;

#include <set>
#include <deque>
#include <algorithm>
#include <iterator>
#include <functional>
#include <iostream>
#include <cstdlib>
#include "print.hpp"
using namespace std;
using namespace std::placeholders;

int main()
{
	set<int, greater<int>> coll1 = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
	deque<int> coll2;
	
	//Note: due to the sorting criterion greater<>() elements have reverse order;
	PRINT_ELEMENTS(coll1, "initialized: ");
	
	//transform all elements into coll2 by multiplying them with 10
	transform(coll1.cbegin(), coll1.cend(), 
	          back_inserter(coll2), 
	          bind(multiplies<int>(), _1, 10));
	PRINT_ELEMENTS(coll2, "transformed: ");
	
	//replace vlaue equal to 70 with 42
	replace_if(coll2.begin(), coll2.end(),
	           bind(equal_to<int>(), _1, 70),
	           42);
	PRINT_ELEMENTS(coll2, "replaced: ");
	
	//remove all elements with vlaues between 50 and 80
	coll2.erase(remove_if(coll2.begin(), coll2.end(),
	                      bind(logical_and<bool>(),
	                           bind(greater_equal<int>(), _1, 50),
	                           bind(less_equal<int>(), _1, 80))),
	            coll2.end());
	PRINT_ELEMENTS(coll2, "removed: ");
	
	system("pause");
}


/*
 * output of program:
 *
 * initialized: 9 8 7 6 5 4 3 2 1
 * transformed: 90 80 70 60 50 40 30 20 10
 * replaced: 90 80 42 60 50 40 30 20 10
 * removed: 90 42 40 30 20 10
 *
 */


// print.hpp

#include<iostream>
#include<string>

//PRINT_ELEMENTS()
// - prints optional string optstr followed by
// - all elements of the collection coll
// - in one line,separated by spaces
template <typename T>
inline void PRINT_ELEMENTS(const T& coll, const std::string& optstr="")
{
	std::cout << optstr;
	for(const auto& elem : coll) {
		std::cout << elem << ' ';
	}
	std::cout << std::endl;
}

 

STL--Function Objects(二)    http://my.oschina.net/daowuming/blog/686879

转载于:https://my.oschina.net/daowuming/blog/685188

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值