您的位置:首页 > 移动开发 > Objective-C

STL--Function Objects(一)

2016-05-31 00:00 459 查看

The Concept of Function Objects

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

[code=language-cpp]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:

[code=language-cpp]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:

[code=language-cpp]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:

Function objects are "function with state". Object that behave like pointers are smart pointers.

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.

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.

[code=language-cpp]#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.

[code=language-cpp]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:

[code=language-cpp]#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;

[code=language-cpp]#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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ STl FunctionObjects