Reverse traits lookup?
<p>I have been looking for a design that solves the following problem.
It will take a few words to describe.</p>

<p>We have four types A1, A2, B, and C.</p>

<p>We would like to write a function fn that takes as parameter a type P.
Using traits, P resolves within A1/A2/B/C to PA1/PA2/PB/PC.</p>

<p>The implementation of fn is the same for PA1 and PA2, but it is
different for PB and PC, both between them as well as from that of
PA1/PA2.</p>

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

struct PA1 {};
struct PA2 {};
struct PB  {};
struct PC  {};

struct A1 { typedef PA1 P; };
struct A2 { typedef PA2 P; };
struct B  { typedef PB  P; };
struct C  { typedef PC  P; };

template&lt;typename T&gt; char fn(typename T::P)
{
    return 'a';
}

char fn(B::P) {   return 'b';  }
char fn(C::P) {   return 'c';  }

int main()
{
    PA1 pa1;
    PA2 pa2;
    PB  pb;
    PC  pc;
    assert( fn&lt;A1&gt;(pa1) == 'a' );
    assert( fn&lt;A2&gt;(pa2) == 'a' );

    assert( fn(pb) == 'b' );
    assert( fn(pc) == 'c' );
}
</code></pre>

<p>The advantage of the code above is that the implementation of fn for
PA1 and PA2 is not repeated.</p>

<p>But here is the snag. The function calls are not symmetric. It is</p>

<pre><code>fn&lt;A1&gt;(pa1)
</code></pre>

<p>and</p>

<pre><code>fn&lt;A2&gt;(pa2)
</code></pre>

<p>for A1/A2/PA1/PA2, but just <code>fn(pb)</code> and
<code>fn(pc)</code> for B/C/PB/PC.</p>

<p>This precludes using fn(..) within yet another (not shown) class
template.</p>

<p>Normally this is not an issue. The template parameter can be deduced
for parameterized functions. That doesn't work here. We'd be asking
the compiler to locate the type among A1/A2/B/C for which P resolves
to one of PA1/PA2/PB/PC.</p>

<p>What would you do?</p>
