手动确定重载函数的优先级



我有多个相同函数的重载。对于某些参数集,几个重载同样适用,我自然会得到一个"模糊重载"错误。我想以某种方式定义这些函数的优先级,以便在出现歧义的情况下,选择优先级最小的函数。

我尝试制作一系列模板助手类,"标签",P<0>P<1>。。。,使得CCD_ 3继承了具有一定上界的CCD_。因此,如果有两个函数f(P<2>)f(P<4>),并且我调用f(P<0>),则选择第一个。

它在实践中不起作用。"干净"的例子与经典"int/long"one_answers"long/int"函数仍然会产生歧义。我试图在函数中添加几个标签参数来增加标签的"权重",但这没有帮助。

这种方法能以某种方式调整吗?

constexpr static int MAX = 20;
template<int N, class Enable = void>
class P {};
template<int N>
class P<N, typename std::enable_if<N < MAX, void>::type> : public P<N+1> {};
void f(int, long, P<2>) {}
void f(long, int, P<5>) {}
int main() {
    f(1, 2, P<0>());
}

首先,您可以简化标记类型的构造,如:

template <int N> struct P : P<N+1> { };
template <> struct P<MAX> { };

接下来,标签类型的自动扶梯只有在是过载的唯一决胜局时才能工作。也就是说,除了标记参数之外,其他所有参数都是等价的。你的电话仍然模糊不清的原因是你最终得到的转换序列是:

f(int, long, P<2>); // #1: Exact, Integral Conversion, P<0> -> ... -> P<2>
f(long, int, P<5>); // #2: Integral Conversion, Exact, P<0> -> ... -> P<2> -> ... -> P<5>

对于每个参数,如果转换序列至少与另一个重载的参数的转换序列一样好,则一个重载只比另一个过载好。这里不是这样的:#1在第一个自变量中比#2更好,在第二个自变量中更差。添加另一个参数并不能改变这个缺陷。

标记类型有帮助的地方是,如果您使用的是具有非不相交条件的SFINAE:

template <class T, std::enable_if_t<cond_a<T>::value>* = nullptr>
void f(T&&, P<0> ) { ... }
template <class T, std::enable_if_t<cond_b<T>::value>* = nullptr>
void f(T&&, P<1> ) { ... }
template <class T, std::enable_if_t<cond_c<T>::value>* = nullptr>
void f(T&&, P<2> ) { ... }
f(whatever, P<0>{});

cond_acond_bcond_c不必是不相交的,并且在每种情况下第一个自变量都是相同的。因此,对于那些没有被SFINAE删除的过载,最后的决胜局就是标签。

最新更新