c – 有没有办法在用户定义的转换中指定优先级?

免责声明:我知道经常不鼓励使用用户定义的隐式转换.但是,在我们的项目中,我们需要对各种模板类进行这些转换才能很好地相互协作.

我需要定义用户定义的转换的优先级,例如:

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>()放置

点赞