模板之泛化仿函式(一)

2021-06-27 07:58:53 字數 3686 閱讀 2557

1 泛化仿函式的要求

引數個數應該是任意的,引數的型別也應該是任意的。

template class functor

;struct t1

};int foo()

int main()

2 被 functor 包覆的多型類 functorimpl 

template class functorimpl

;template class functorimpl < r, nulltype >

// 虛析構很重要

};template class functorimpl < r, typelist_1(p1) >

};template class functorimpl < r, typelist_2(p1, p2) >

};// 帶有 4、5、...更多引數的 functorimpl

3 functor 遵循典型的 handle-body 實現手法

template class functor

functor(const functor& rhs) : spimpl_(rhs.spimpl_.get()->clone()) // copy constructor

{} functor& operator= (const functor& rhs) // assignment operator

explicit functor(std::auto_ptrspimpl) : spimpl_(spimpl)

{}public:

// 使用 typeatnonstrict 模板取得 typelist 中某個位置上的型別,parmn 是typelist的第n個型別,如果 typelist 元素個數少於 n,獲得結果將是 nulltype

typedef tlist parmlist;

typedef r resulttype;

typedef typename typeatnonstrict::result parm1;

typedef typename typeatnonstrict::result parm2;

r operator()()

r operator()(parm1 p1)

r operator()(parm1 p1, parm2 p2)

.....

};

4 處理仿函式

任何 class 實體只要定義有 operator(),都是仿函式。 functor 滿足這一定義,所以 functor 是仿函式。因此「以仿函式 fun之物件為引數」的 functor 建構函式,是個「被fun引數化」的templated 建構函式

template class functor

;template template // 注:c++ 將這類**稱為「位於 class 本體之外的 member template 定義式」

functor::functor(const fun& fun)

: spimpl_(new functorhandler(fun))

為了實現這個建構函式,我們需要乙個從 functorimpl派生而來的class template functorhandler ,其中儲存了乙個型別為 fun 的物件,並將 operator() **給該物件。

// functorhandler

template class functorhandler

: public functorimpl < typename parentfunctor::resulttype,

typename parentfunctor::parmlist >

functorhandler* clone() const

public:

typedef typename parentfunctor::resulttype resulttype;

resulttype operator()()

resulttype operator()(typename parentfunctor::parm1 p1)

resulttype operator()(typename parentfunctor::parm1 p1,

typename parentfunctor::parm2 p2)

private:

fun fun_;

};

struct testfunctor

};void test()

int main()

5 引數和返回型別的轉化

const char* testfunc(double, double)

int main()

6 處理 pointer to member function

// member function 

template class memfunhandler

: public functorimpl < typename parentfunctor::resulttype,

typename parentfunctor::parmlist >

memfunhandler* clone() const

resulttype operator()()

resulttype operator()(typename parentfunctor::parm1 p1)

resulttype operator()(typename parentfunctor::parm1 p1,

typename parentfunctor::parm2 p2)

private:

pointertoobj pobj_;

pointertomemfn pmemfn_;

};template class functor

;template template functor::functor(const pointertoobj& pobj, const pointertomemfn& pmemfn)

: spimpl_(new memfunhandler(pobj, pmemfn))

class parrot

void speak() };

int main()

7 過載函式傳給 functor 的歧義錯誤

void testfunction(int i, double d)

void testfunction(int i)

int main()

如果你過載 testfunction,就得想辦法消除歧義性。原因是如果 testfunction 被過載,其名稱(符號)所代表的型別就不再有明確定義。

如果出現過載,兩種方法可以識別其中某個函式:一使用賦值(assignment),二使用轉型(cast)

int main()

賦值(assignment)和靜態轉型(static cast)都可以讓編譯器知道,你感興趣的實際上是」引數為 int 和 double,返回型別為 void「的那個 testfunction 函式。

第五章 泛化仿函式

該章節有點類似於實現了function和bind操作 functor.h的實現 pragma once include functorimpl.h include functorhandler.h r即返回值,tlist即引數列表 template 預設不帶引數 class cfunctor cfu...

泛型仿函式三

成員函式指標 有些c 編譯器廠商定義出一種新型別,讓你可以通過以下語法儲存operator.操作結果 void closure geronimoswork geronimo.pactivity geronimoswork template class memfunhandler public fun...

Monads之仿函式

def map a,b oa option a f a b option a 仿函式就是實現了map的資料型別,其簽名如上,即接受乙個函式將乙個型別構造器裡的型別轉化成另一種型別,我們可以根據這個規則,把 規則 抽取成乙個trait,如下 trait functor f 我們實現乙個list型別的f...