1. 程式人生 > >for_each各種情況下的函式物件使用方法

for_each各種情況下的函式物件使用方法

原創作者:http://oomusou.cnblogs.com

Introduction

學習過STL的container後,想要存取每一個iterator,你一定寫過以下的程式

#include <vector>

#include <iostream>

usingnamespace std;

int main() {

int ia[] = {1, 2, 3};

  vector<int> ivec(ia, ia + sizeof(ia) / sizeof(int));

for(vector<

int>::const_iterator iter = ivec.begin(); iter != ivec.end(); ++iter) {

    cout << *iter << endl;

  }

}

執行結果

1

2

3

當時我覺得STL什麼都好,就是以下這一串又臭又長

for(vector<int>::const_iterator iter = ivec.begin(); iter != ivec.end(); ++iter) {

若不常寫,一時還會寫不出來,其實若配合container,C++其實不應該這樣像寫迴圈,正確的方式該使用for_each(),語法會變得相當簡單。

for_each()事實上是個function template,其實做如下[effective STL item 41]

template<typename InputIterator, typename Function>

Function for_each(InputIterator beg, InputIterator end, Function f) {

while(beg != end) 

    f(*beg++);

}

由以上source可知,for_each()只能配合global function和function object。

以下我們將對procedure based(基於程式)、object oriented(面向物件)、generics(通用)三種paradigm與for_each()搭配做探討。

ProcedureBased與for_each()搭配

1.不傳入引數

 1 /* 

 2(C) OOMusou 2007 http://oomusou.cnblogs.com

 3Filename    : GenericAlgo_for_each_GlobalFunction.cpp

 4Compiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++

 5Description : Demo how to use for_each with global function

 6Release     : 05/11/2007 1.0

 7*/

 8#include <iostream>

 9#include <vector>

10#include <iostream>

11#include <algorithm>

12

13usingnamespace std;

14

15void printElem(int& elem) {

16  cout << elem << endl;

17}

18

19int main() {

20int ia[] = {1, 2, 3};

21  vector<int> ivec(ia, ia + sizeof(ia) / sizeof(int));

22

23  for_each(ivec.begin(), ivec.end(), printElem);

24}

執行結果

1

2

3

只需將vector::begin(),vector::end()和global function name傳給for_each()即可,再也不用for迴圈那種複雜的語法了。 

2.傳入引數

若要傳引數給global function,就不能再只傳global function name而已,必須透過ptr_fun()這個function adapter將global function轉成function object,然後再用bind2nd()將引數bind成一個functionobject。

8#include <iostream>

9#include <vector>

10#include <iostream>

11#include <algorithm>

12#include <functional>

13

14usingnamespace std;

16void printElem(int elem, constchar* prefix) {

17  cout << prefix << elem << endl;

18}

19int main() {

21int ia[] = {1, 2, 3};

22  vector<int> ivec(ia, ia + sizeof(ia) / sizeof(int));

23

24  for_each(ivec.begin(), ivec.end(), bind2nd(ptr_fun(printElem), "Element:"));

25}

ptr_fun輔助構造一般函式指標的point_to_binary_function或是

     pointer_to_unary_function介面卡例項

構造一元函式指標適配申明如下:

template<typename Arg, typename Result>

  pointer_to_unary_function<Arg, Result, Result (*)(Arg)>   ptr_fun(Result (*_pfunc)(Arg));

首先,STL定義了binder2nd類,該類繼承自unary_function,在類的函式運算體中完成對二元函式的引數傳遞和呼叫。binder2nd的例項構造通常比較冗長,bind2nd函式用於輔助構造binder2nd的一個例項(返回一個binder2nd類的物件,這個類應該過載了()運算子)。

bind2nd的原型宣告為:

template<typename Operation, typename Type>
   binder2nd<Operation> bind2nd(
      const Operation& _Func, 
      const Type& _Right
   );

binder2nd函式詳解

執行結果

Element:1

Element:2

Element:3

ObjectOriented與for_each()搭配

1.不傳入引數

使用function object

 1 /* 

 2(C) OOMusou 2007 http://oomusou.cnblogs.com

 3Filename    : GenericAlgo_for_each_FunctionObject.cpp

 4Compiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++

 5Description : Demo how to use for_each with function object

 6Release     : 05/11/2007 1.0

 7*/

 8#include <iostream>

 9#include <vector>

10#include <iostream>

11#include <algorithm>

12

13usingnamespace std;

14

15struct printElem {

16voidoperator() (int elem) {

17    cout << elem << endl;

18  } 

19};

20

21int main() {

22int ia[] = {1, 2, 3};

23  vector<int> ivec(ia, ia + sizeof(ia) / sizeof(int));

24

25  for_each(ivec.begin(), ivec.end(), printElem());//傳入一個物件

26}

執行結果

1

2

3

2.傳入引數

若使用function object,也可以將引數傳給printElem(),通過constructor的技巧接收引數。

 1 /* 

 2(C) OOMusou 2007 http://oomusou.cnblogs.com

 3Filename    : GenericAlgo_for_each_FunctionObjectWithParameter.cpp

 4Compiler    : Visual C++ 8.0 / BCB 6.0 / gcc 3.4.2 / ISO C++

 5Description : Demo how to use for_each with function object with parameter

 6Release     : 05/11/2007 1.0

 7*/

 8#include <iostream>

 9#include <vector>

10#include <iostream>

11#include <algorithm>

12

13usingnamespace std;

14

15struct printElem {

16constchar* _prefix;

17

18  printElem(constchar* prefix) : _prefix(prefix) {}

19

20voidoperator() (int elem) {

21    cout << _prefix << elem << endl;

22  } 

23};

24

25int main() {

26int ia[] = {1, 2, 3};

27  vector<int> ivec(ia, ia + sizeof(ia) / sizeof