我一直在寻找一种解决以下问题的设计。
这将需要几句话来描述。
我们有四种类型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之一。
你会怎么做?
最佳答案
我认为您在这里混淆了两件事:
不排除PA1
和PA2
是具有不同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/