Tuesday, 31 March 2015

Function adaptors

Function adaptors with code examples:

Function adaptors work only with function object classes with argument types and result type defined.

Negators:
A negator is a kind of function adapter used to reverse the sense of predicate function objects.
Negators not1 and not2 take a unary and a binary predicate correspondingly and return their complements.

template <class ClsPredicate>

class ClsUnaryNegate : public unary_function<ClsPredicate::argument_type, bool> {

protected:

ClsPredicate objPred;

public:

ClsUnaryNegate(const ClsPredicate& oc_ObjPreicate) : objPred(oc_ObjPreicate) {}

bool operator()(const argument_type& oc_ObjPreicate) const { return !objPred(oc_ObjPreicate); }

};

template <class ClsPredicate>

ClsUnaryNegate<ClsPredicate> not1(const ClsPredicate& objPred) {

return ClsUnaryNegate<ClsPredicate>(objPred);

}

template <class ClsPredicate>

class ClsNegate : public binary_function<ClsPredicate::first_argument_type,

ClsPredicate::second_argument_type, bool> {

protected:

ClsPredicate objPred;

public:

ClsNegate(const ClsPredicate& oc_ObjPreicate) : objPred(oc_ObjPreicate) {}

bool operator()(const first_argument_type& oc_ObjPreicate,

const second_argument_type& ocTest) const {

return !objPred(oc_ObjPreicate, ocTest);

}

};

template <class ClsPredicate>

ClsNegate<ClsPredicate> not2(const ClsPredicate& objPred) {

return ClsNegate<ClsPredicate>(objPred);

}


Binders:

We can use STL binders to use binary function objects as unary function objects in many STL algorithms which need them.
Here is the sample code snippet to find the count of strings in a vector of strings who are equal to a certain strings:
 vector<string> StringList;

 StringList.push_back("TEst");

 StringList.push_back("Test123");

 StringList.push_back("Test12345");

 StringList.push_back("Tester3343433");


template <class ClsOperate>

class ClsTest : public unary_function<ClsOperate::second_argument_type, ClsOperate::result_type>

{

protected:

ClsOperate ocOperate;

ClsOperate::first_argument_type value;

public:

ClsTest (const ClsOperate& ocTest, const ClsOperate::first_argument_type& ocArgType) : ocOperate(ocTest), value(ocArgType)

  {}

result_type operator()(const argument_type& ocTest) const

  { return ocOperate(value, ocTest); }

};

template <class ClsOperate, class T>

ClsTest<ClsOperate> bind1st(const ClsOperate& ocOperate, const T& ocTest)

  { return ClsTest<ClsOperate>(ocOperate, ClsOperate::first_argument_type(ocTest)); }

template <class ClsOperate>

class ClsTest2 : public unary_function<ClsOperate::first_argument_type,

ClsOperate::result_type> {

protected:

ClsOperate ocOperate;

ClsOperate::second_argument_type value;

public:

ClsTest2 (const ClsOperate& ocTest, const ClsOperate::second_argument_type& ocArgType) : ocOperate(ocTest), value(ocArgType)

  {}

result_type operator ()(const argument_type& ocTest) const

  { return ocOperate(ocTest, value); }

};

template <class ClsOperate, class T>

ClsTest2<ClsOperate> ocClsTest2 (const ClsOperate& ocOperate, const T& ocTest)

  { return ClsTest2<ClsOperate>(ocOperate, ClsOperate::second_argument_type(ocTest)); }


Adaptors for pointers to functions:

To allow pointers to functions are provided to allow pointers to unary and binary functions to work with the other function adaptors provided in the library. To work with function adaptors the library provides:
template <class ClsOne, class ClsRes>

class pointer_to_unary_function : public unary_function<ClsOne, ClsRes>

{

protected:

ClsRes (*pcPtr)(ClsOne);

public:

pointer_to_unary_function (ClsRes (*pcTestRes)(ClsOne)) : pcPtr(pcTestRes)

  {}

ClsRes operator ()(ClsOne pcTestRes) const

  { return pcPtr(pcTestRes); }

};

template <class ClsOne, class ClsRes>

pointer_to_unary_function<ClsOne, ClsRes> ptr_fun (ClsRes (*pcTestRes)(ClsOne)) {

return pointer_to_unary_function<ClsOne, ClsRes> (pcTestRes);

}

template <class Argument1, class Argument2, class ClsRes>

class pointer_to_binary_function : public binary_function<Argument1, Argument2, ClsRes>

{

protected:

ClsRes (*pcPtr)(Argument1, Argument2);

public:

  pointer_to_binary_function (ClsRes (*pcTestRes)(Argument1, Argument2)) : pcPtr(pcTestRes) {}

  ClsRes operator ()(Argument1 pcTestRes, Argument2 ResArg) const { return pcPtr(pcTestRes, ResArg); }

};

template <class Argument1, class Argument2, class ClsRes> pointer_to_binary_function<Argument1, Argument2, ClsRes>

ptr_fun (ClsRes (*pcTestRes) (Argument1, Argument2))

  {  return pointer_to_binary_function<Argument1, Argument2, ClsRes>(pcTestRes); }


Compilation systems that have multiple pointer to function types have to provide additional ptr_fun
template functions.

No comments: