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.

Advertisements

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 which allocators the DirectShow filters are using?


In my DVR media player projects, I made two filters: one source filter(push) to read data from DVR, and one decoder (transform) filter to decode the video. Most allocator work is taken care of by DirectShow base classes. I dig deeper into the allocators when I was doing renderless mode.
The question is: How many allocators are in the graph and where are they from?
There are two, one from decoder’s input pin, and one from VMR’s input pin.
Here are my findings by stepping into the base class code.
First allocator (used by source filter):

CBaseOutputPin::DecideAllocator(IMemInputPin *pPin, __deref_out IMemAllocator **ppAlloc)
//*ppAlloc is the allocator the source filter's output pin will be using.
//*ppAlloc is from decoder's input pin. 
//It's created (by CreateMemoryAllocator, instead of re-used) beause decoding isn't inplace
//instead of using allocator from next input pin, this pin can override InitAllocator to use it's own.
//*ppAlloc is apporved by DecideBufferSize()

Second allocator (used by decoder filter):

CBaseOutputPin::DecideAllocator(IMemInputPin *pPin, __deref_out IMemAllocator **ppAlloc)
//*ppAlloc is the allocator the decoder filter's output pin will be using.
//*ppAlloc is from VMR's input pin.
//*ppAlloc is apporved by DecideBufferSize()

Summary: for a non-inplace transform filter, in most circumstances, it’s input pin provides allocator for it’s upstream output pin, and it’s outpin uses the allocator from it’s downstream’s input pin.