A functor from scratch that works with std bind2nd


For a functor to work with bind2nd, it usually derives from binary_function.
However, making one from scratch is not much work as illustrated in the following.

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;
typedef int first_argument_type;
typedef int second_argument_type;
};
void Test_bind2nd()
{
int a[] = {0, 2, 3 };
int c = count_if ( a, a + 3, bind2nd(FunctorAdd(), 0) ); //bind2nd is a system adapter in std
//count the ones that are not 0
_ASSERT(c == 2); //this proves FunctorAdd works well with bind2nd
}

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
}

Find out the length of array


void TestLengthArray()
{
	enum {E_ARRAY_LEN = 2};
	int *a = new int[E_ARRAY_LEN];
	size_t iSize = _msize(a) / sizeof a[0];
	_ASSERT(iSize == E_ARRAY_LEN); //here we got the length of the array
}

MSDN didn’t mention if _msize can be used for ‘new’; it just seems working.
This is not supported by the standard, but good to know it’s possible at runtime.

Why EXACTLY does the compiler need help from dllimport?


extern "C" __declspec(dllimport) void __stdcall func(); //func() is in a DLL file and called by an executable

Many articles say that dllimport makes more efficient code by bypassing a jump.
But why is there a jump at the first place?
Short answer: because there is not enough room for the linker to fill in with a function pointer.

Long answer:
the compiler doesn’t know whether func() is from dll or not, and it assumes it’s not(to save space and time). The compiler leaves a slot at the spot where func() is called for the linker to fill in with func()’s address. If it’s a non-dll function, no problem. If it IS a dll function, the linker doesn’t know the function’s address; it only knows the pointer pointing to this address(IAT entry). Here is the linker’s solution: using a stub.
The linker fills the slot with the address of the stub. The stub’s code has JMP to jump to where the function pointer points to(in IAT).
This explains why stub(jump) is needed. Of course if the compiler knows it’s a dll function, it doesn’t need the stub, because the compiler can simply leave the slot big enough for the linker to fill it with the function pointer(and ‘DWORD PTR’, but ignore it to keep it simple).