Transforming a parameterization by two classes to a parameterization by one class
<p>The following code has a little bit of unpleasantness.</p>

<pre><code>#include &lt;cassert&gt;

template&lt;typename S&gt; struct PA1 {}; template&lt;typename S&gt; struct QA1 {};
template&lt;typename S&gt; struct PA2 {}; template&lt;typename S&gt; struct QA2 {};
template&lt;typename S&gt; struct PB  {}; template&lt;typename S&gt; struct QB  {};
template&lt;typename S&gt; struct PC  {}; template&lt;typename S&gt; struct QC  {};

template&lt;typename S&gt; struct A1 { typedef PA1&lt;S&gt; P; typedef QA1&lt;S&gt; Q; };
template&lt;typename S&gt; struct A2 { typedef PA2&lt;S&gt; P; typedef QA2&lt;S&gt; Q; };
template&lt;typename S&gt; struct B  { typedef PB&lt;S&gt;  P; typedef QB&lt;S&gt;  Q; };
template&lt;typename S&gt; struct C  { typedef PC&lt;S&gt;  P; typedef QC&lt;S&gt;  Q; };

template&lt;typename PA, typename QA&gt;
char fn(PA, QA) {
    return 'a';
}

template&lt;typename S&gt; char fn(PB&lt;S&gt;, QB&lt;S&gt;) { return 'b'; }
template&lt;typename S&gt; char fn(PC&lt;S&gt;, QC&lt;S&gt;) { return 'c'; }

template&lt;typename T&gt;
struct Action
{
    char z;
    Action(typename T::P p, typename T::Q q)
    {
        z = fn(p, q);
    }
};

int main()
{
    PA1&lt;int&gt; pa1; QA1&lt;int&gt; qa1;
    PA2&lt;int&gt; pa2; QA2&lt;int&gt; qa2;
    PB&lt;int&gt;  pb;  QB&lt;int&gt;  qb;
    PC&lt;int&gt;  pc;  QC&lt;int&gt;  qc;

    assert( fn(pa1, qa1) == 'a' );
    assert( fn(pa2, qa2) == 'a' );

    assert( fn(pb, qb) == 'b' );
    assert( fn(pc, qc) == 'c' );

    Action&lt;A1&lt;int&gt; &gt; aa1 = Action&lt;A1&lt;int&gt; &gt;(pa1, qa1);    assert( aa1.z == 'a' );
    Action&lt;A2&lt;int&gt; &gt; aa2 = Action&lt;A2&lt;int&gt; &gt;(pa2, qa2);    assert( aa2.z == 'a' );

    Action&lt;B&lt;int&gt; &gt; ab = Action&lt;B&lt;int&gt; &gt;(pb, qb );    assert( ab.z == 'b' );
    Action&lt;C&lt;int&gt; &gt; ac = Action&lt;C&lt;int&gt; &gt;(pc, qc );    assert( ac.z == 'c' );
}
</code></pre>

<p>Even though PA and QA always arise in tandem (PA1 with QA1 and PA2 with QA2), we write</p>

<pre><code>template&lt;typename PA, typename QA&gt;
char fn(PA, QA) { ... }
</code></pre>

<p>It would be much nicer to write</p>

<pre><code>template&lt;typename A&gt;
char fn(typename A::P, typename A::Q) {
    return 'a';
}
</code></pre>

<p>Can you suggest a modification that would make that possible?</p>
