我一直在寻找一种解决以下问题的设计。
这将需要几句话来描述。

我们有四种类型A1,A2,B和C。

我们想编写一个函数fn,将类型P作为参数。
使用特征,P在A1 / A2 / B / C内解析为PA1 / PA2 / PB / PC。

fn的实现与PA1和PA2相同,但是
PB和PC之间的差异以及两者之间的差异
PA1 / PA2。

#include <cassert>

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<typename T> 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<A1>(pa1) == 'a' );
    assert( fn<A2>(pa2) == 'a' );

    assert( fn(pb) == 'b' );
    assert( fn(pc) == 'c' );
}

上面代码的优点是fn为
PA1和PA2不重复。

但是这里有障碍。函数调用不对称。它是
fn<A1>(pa1)


fn<A2>(pa2)

对于A1 / A2 / PA1 / PA2,但仅fn(pb)
B / C / PB / PC的fn(pc)

这就排除了在另一个(未显示)类中使用fn(..)
模板。

通常这不是问题。可以推导出template参数
用于参数化功能。这在这里不起作用。我们会问
编译器在P解析的A1 / A2 / B / C中定位类型
到PA1 / PA2 / PB / PC之一。

你会怎么做?

最佳答案

我认为您在这里混淆了两件事:



不排除PA1PA2是具有不同typedef的不同类型。

因此,我们可以这样使用:

template <typename PA>
char fn(PA pa) {
  typedef typename PA::type Type; // A1 or A2
  return 'a';
}

char fn(PB);
char fn(PC);

如果您实际上不能修改P本身,则可以随时引入traits类。
template <typename T>
struct PTraits;

template <>
struct PTraits<PA1> { typedef A1 type; };

template <>
struct PTraits<PA2> { typedef A2 type; };

// ...

我会注意到,Herb Sutter建议不要使用函数特化,而应首选重载,因为重载(尤其是涉及模板)之间的相互作用非常棘手...而且很难弄清从给定调用哪个函数参数集。

关于c++ - 反向特征查询?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5642819/

10-16 04:23