functor vs lamba


Demonstrated by std::sort
Comparing to function pointers, lambda can access all variables in enclosing scope.
Comparing to function pointers, functor have state, with help from data members in the functor class.

bool MyCompare(const int& a, const int& b)
{
	return a > b;
}

class MyComparer
{
public:
	MyComparer(bool bCompareByAbsValue)
	{
		mbCompareByAbsValue = bCompareByAbsValue;
	}
	bool operator()(const int& a, const int& b)
	{
		if (mbCompareByAbsValue)
			return abs(a) > abs(b);
		else
			return a > b;
	}
private:
	bool mbCompareByAbsValue;
};
void output(string by, int * aInt, size_t nLen)
{
	cout << "sort by " << by << " descending order: " << endl;
	for (int i = 0; i < nLen; i++)
		cout << aInt[i] << " ";
	cout << endl;

}
void TestFunctionPtrFunctorLambda()
{
	const int LENGTH = 3;
	int nLen = LENGTH;
	int aInt[LENGTH] = {2, -3, 1};
	int * pInt = aInt;
	std::sort(pInt, pInt + nLen, MyCompare);
	output("function pointer", aInt, nLen);

	bool bCompareByAbsValue = true;
	std::sort(pInt, pInt + nLen,
		[bCompareByAbsValue](int a, int b) {
		if (bCompareByAbsValue)
			return abs(a) > abs(b);
		else
			return a > b;
	});
	output("lambda, absolute value", aInt, nLen);

	std::sort(pInt, pInt + nLen, MyComparer(bCompareByAbsValue));
	output("functor, absolute value", aInt, nLen);
}

output:
sort by function pointer descending order:
2 1 -3
sort by lambda, absolute value descending order:
-3 2 1
sort by functor, absolute value descending order:
-3 2 1

Advertisements

Safe Bool Idiom


How to allow if(myType), but disallow bool b = myType;
C++11’s solution is keyword “explicit” like so:
explicit operator bool() const;
This still allows if(myType) by taking advantage of the fact that there is already an explicit cast to bool with if.
This disallows implicit cast to bool, therefore disallows operation such as comparison and arithmetic operations.

typename vs class (Visual Studio 2010)


Under what circumstances does NOT ‘class’ replace ‘typename’?

struct C
{
class CC{};
typedef CC CC2;
};
template<class T> //using 'class' is fine
struct D
{
typename T::CC2 c1; //'typename' cannot be prelaced by 'class'
class T::CC c2; //using 'class' is fine
//T::CC c3; //error: 'T::CC' : dependent name is not a type
//class T::CC2 c4; //error C2242: typedef name cannot follow class/struct/union
//T::CC2 c5; //error: 'T::CC2' : dependent name is not a type
};
D<C> a;

Summary: if the subtype if not typedef-ed, class can do the job of typename.
Otherwise, it has to be typename.

A minimum implementation of std bind2nd from scratch


This home-made Bind2nd, which simulates std::bind2nd, is described as following:
1. make a regular two-parameter functor and add some typedefS, which will be used by the adapter.
2. make a one-parameter functor based one the typedefS.
3. make the adapter, which returns a one-parameter functor.

struct FunctorAdd //takes two parameters, operator() returns the sum of the two.
{
	int operator()(const int & i, const int & j) const
	{       return i+j;
	}
	typedef int result_type; //these typedef are for adapter Bind2nd
	typedef int first_argument_type;
	typedef int second_argument_type;
};
template<typename T>
struct FunctorWithOneParameter //this is what Bind2nd transforms FunctorAdd to
{
	T mt;
	typename T::second_argument_type mr; //'typename' cannot be prelaced by 'class'
	FunctorWithOneParameter(const T& t, typename T::second_argument_type r): mt(t), mr(r) { }
	typename T::result_type operator()(typename const T::first_argument_type& l) { return mt(l, mr); }
};
template<typename T>
FunctorWithOneParameter<T> Bind2nd(const T& t, typename T::second_argument_type r) //Bind2nd is the home-made adapter
{
	return FunctorWithOneParameter<T>(t, r);
}

void TestAdapter()
{	int iBind = Bind2nd(FunctorAdd(), 3)(1); //bind by home-made Bind2nd
	_ASSERT(iBind == 4);
	int a[] = {0, 2, 3 };
	int c = count_if ( a, a + 3, Bind2nd(FunctorAdd(), 0) );//count the ones that are not 0
	_ASSERT(c == 2); //this proves Bind2nd is a successful adapter for FunctorAdd
}