免责声明:我知道经常不鼓励使用用户定义的隐式转换.但是,在我们的项目中,我们需要对各种模板类进行这些转换才能很好地相互协作.
我需要定义用户定义的转换的优先级,例如:
struct X{}
struct Y{}
struct Z{
operator X(){...}
operator Y(){...}
}
void foo(X x){...}
void foo(Y y){...}
// somewhere in some template client code
...{
Z z = ...;
...
foo(z); // WILL NOT COMPILE
}
这不会编译,因为从Z到X或Y的转换是不明确的.有没有办法解决这种歧义.即,我可以以某种方式告诉编译器:如果有一个函数为X和Y重载,那么更喜欢将Z转换为X而不是无法编译.
我知道没有简单的方法来指定它.但也许一些我不知道的模板魔术和包装模板结构可能会成功.我被允许更改客户端代码.我不能使用显式转换,因为客户端代码是模板化代码,不知道类型Z和foo的可用重载.
最佳答案 您可以执行类似“优先级调用”的操作,使用如下模式:
struct P2 {};
struct P1: P2 {};
template<class A>
void foo(A x, P1, typename std::common_type<X,A>::type* =nullptr)
{ foo(static_cast<X>(x)); }
template<class A>
void foo(A y, P2, typename std::common_type<Y,A>::type* =nullptr)
{ foo(static_cast<Y>(y)); }
template<class A> void foo(A a) { foo(a,P1()); }
作为P1的基础和用P1进行的调用,如果common_type可以编译,则第一个版本进行.如果它无法编译,第一个版本就像不存在(SFINAE),第二个版本就是如此.如果它也不能编译…如果A只是X或只是Y,则调用相应的原始foo,否则这不能编译为不兼容的类型.
请注意,您甚至可以将“优先级”概括为
template<size_t N> struct P: P<N+1> {}
template<> struct P<10> {}
声明SFINAE函数采用P 1,P 2和P 2.等等至P< 10>,并且将根调用与P< 0>()放置