CGL开发手记之三--CGL中的"函数对象"
需要注意的是,本节题目中"函数对象"四字是加了双引号的,因为C语言中没有办法做到类C++中函数对象的做法,CGL中采用的替代手段是使用函数指针.
首先需要短暂回顾STL中的函数对象以及函数对象适配器等概念.
STL中的最基本的函数对象分为三类: generator, unary function,binary function,其中的generator是无参数函数,unary function是单参数函数,binary function是双参数函数.注意,以上只是提到的三者的传入参数的数量,还没有涉及到它们所要返回的参数类型.一般的,三者都是以template参数作为自己返回参数的类型,但是当unary function和binary function返回参数是bool型的时候,分别称它们为:predicate和binary predicate,这是因为STL中很多范型参数的调用需要传入一个函数对象进行元素的比较.如sort,find_if等函数.
函数对象适配器分为两类:一类是绑定器(binder),另外一类是取反器(negator),绑定器用于绑定函数对象中的某个参数,取反器用于将函数对象的返回值进行翻转,一般的,可以使用取反器的函数对象都是那些返回值为bool型的函数对象.
CGL中不能实现函数适配器,因为绑定器在绑定参数的时候是通过将所需要绑定的参数作为模版参数传递给函数对象类进行参数绑定的,如:
template
<
class Operation
>
class binder2nd
:
public
unary_function
<
typename
Operation::first_argument_type,
typename
Operation::result_type
>
{
protected:
Operation op;
typename
Operation::second_argument_type value;
public
:
binder2nd(
const
Operation
&
x,
const
typename
Operation::second_argument_type
&
y)
: op(x), value(y) {}
typename
Operation::result_type
operator()(
const
typename
Operation::first_argument_type
&
x)
const
{
return op(x, value);
}
};

template
<
class Operation, class T
>
inline binder2nd
<
Operation
>
bind2nd(
const
Operation
&
op,
const
T
&
x) {
typedef
typename
Operation::second_argument_type arg2_type;
return binder2nd
<
Operation
>
(op, arg2_type(x));
}

以上是绑定器bind2nd函数的实现,你可以看到这个函数是返回一个binder2nd的函数对象类,而所需要绑定的参数作为binder2nd的value参数存储起来,在调用binder2nd的operator()时再使用value参数,由于C中没有办法做到重载operator()函数,所以不能实现binder.
同样的,C中也没有办法实现negator函数对象适配器,见代码:
template
<
class Predicate
>
class unary_negate
:
public
unary_function
<
typename
Predicate::argument_type, bool
>
{
protected:
Predicate pred;
public
:
explicit
unary_negate(
const
Predicate
&
x) : pred(x) {}
bool operator()(
const
typename
Predicate::argument_type
&
x)
const
{
return !pred(x);
}
};

template
<
class Predicate
>
inline unary_negate
<
Predicate
>
not1(
const
Predicate
&
pred) {
return unary_negate
<
Predicate
>
(pred);
}

以上是negator函数not1函数的实现.可以看到这个函数返回一个unary_negate函数对象,而在这个函数对象重载的operator()中对pred函数的返回值进行取反以达到negator函数对象适配器的作用,同样的,用于C中不能做到重载operator(),所以没有办法实现negator函数对象适配器.
STL中还有一些预定义的函数对象如plus,equal_to等,见代码:
template
<
class T
>
struct plus :
public
binary_function
<
T, T, T
>
{
T operator()(
const
T
&
x,
const
T
&
y)
const
{ return x
+
y; }
};

plus的函数参数是通过模版参数T传入的,任何想要采用plus的类型都需要提供operator + 操作符.因为这个特点,C中也没有办法实现这些预定义的函数对象.
鉴于以上的原因,CGL中的"函数对象"被定义为几种函数指针:
typedef bool_t (
*
binary_predicate)(data_t tData1, data_t tData2);
typedef void (
*
binary_func)(data_t tData1, data_t tData2, data_t tResult);
typedef void (
*
binary_func2)(data_t tData1, data_t tData2);

typedef bool_t (
*
unary_predicate)(data_t tData);
typedef void (
*
unary_func)(data_t tData, data_t tResult);
typedef void (
*
unary_func2)(data_t tData);

typedef void (
*
generator_func)(data_t tResult);
typedef void (
*
generator_func2)();

这些函数指针的返回值只有两种,bool_t和void,当需要返回除了boot_t之外的返回值时,将保存返回值的指针tResult传入函数中保存返回值,所有CGL中使用的函数指针都只可能是以上的几种函数指针类型.
首先需要短暂回顾STL中的函数对象以及函数对象适配器等概念.
STL中的最基本的函数对象分为三类: generator, unary function,binary function,其中的generator是无参数函数,unary function是单参数函数,binary function是双参数函数.注意,以上只是提到的三者的传入参数的数量,还没有涉及到它们所要返回的参数类型.一般的,三者都是以template参数作为自己返回参数的类型,但是当unary function和binary function返回参数是bool型的时候,分别称它们为:predicate和binary predicate,这是因为STL中很多范型参数的调用需要传入一个函数对象进行元素的比较.如sort,find_if等函数.
函数对象适配器分为两类:一类是绑定器(binder),另外一类是取反器(negator),绑定器用于绑定函数对象中的某个参数,取反器用于将函数对象的返回值进行翻转,一般的,可以使用取反器的函数对象都是那些返回值为bool型的函数对象.
CGL中不能实现函数适配器,因为绑定器在绑定参数的时候是通过将所需要绑定的参数作为模版参数传递给函数对象类进行参数绑定的,如:
























同样的,C中也没有办法实现negator函数对象适配器,见代码:


















STL中还有一些预定义的函数对象如plus,equal_to等,见代码:






鉴于以上的原因,CGL中的"函数对象"被定义为几种函数指针:











