The following code has a little bit of unpleasantness.
#include
template struct PA1 {}; template struct QA1
As I understand the question and its predecessors, the task is a specialization of function template on a class template regardless of its template parameter.
Generic solution:
#include
//remember the value of the argument S to retrieve it later
template struct PA1 { typedef S S; };
template struct PA2 { typedef S S; };
template struct PB { typedef S S; };
template struct PC { typedef S S; };
//helper: generic version of fn for any parameters except PB и PC
template
struct FN
{
static char fn() { return 'a'; }
};
//helper: fn specialized for class template PB
template
struct FN, S>
{
static char fn() { return 'b'; }
};
//helper: fn specialized for class template PC
template
struct FN, S>
{
static char fn() { return 'c'; }
};
//fn relies on compiler's type deduction to avoid specifying of template parameter explicitly
template
char fn(T t)
{
return FN< T, T::S>::fn();
}
//usage
int main()
{
PA1 pa1;
PA2 pa2;
PB pb;
PC pc;
assert( (fn(pa1)) == 'a' );
assert( (fn(pa2)) == 'a' );
assert( (fn(pb)) == 'b' );
assert( (fn(pc)) == 'c' );
}
Applying this method to your case:
#include
template struct PA1 { typedef S S; }; template struct QA1 {};
template struct PA2 { typedef S S; }; template struct QA2 {};
template struct PB { typedef S S; }; template struct QB {};
template struct PC { typedef S S; }; template struct QC {};
template struct A1 { typedef PA1 P; typedef QA1 Q; };
template struct A2 { typedef PA2 P; typedef QA2 Q; };
template struct B { typedef PB P; typedef QB Q; };
template struct C { typedef PC P; typedef QC Q; };
template
struct FN
{
static char fn() { return 'a'; }
};
template
struct FN, S>
{
static char fn() { return 'b'; }
};
template
struct FN, S>
{
static char fn() { return 'c'; }
};
template
char fn() //or char fn(A* a)
{
return FN::fn();
}
template
struct Action
{
char z;
//so the constructor accepts only correct combinations of p and q
Action(typename T::P p, typename T::Q q)
{
z = fn(); //or fn((T*)NULL);
}
};
int main()
{
PA1 pa1; QA1 qa1;
PA2 pa2; QA2 qa2;
PB pb; QB qb;
PC pc; QC qc;
Action > aa1 = Action >(pa1, qa1); assert( aa1.z == 'a' );
Action > aa2 = Action >(pa2, qa2); assert( aa2.z == 'a' );
Action > ab = Action >(pb, qb ); assert( ab.z == 'b' );
Action > ac = Action >(pc, qc ); assert( ac.z == 'c' );
}