手动优先处理重载的函数

时间:2016-10-06 20:26:24

标签: c++ templates overloading

我有多个相同功能的重载。对于某些参数集,几个重载相同,我自然会得到一个“模糊过载”错误。我想在某种程度上定义这些函数的优先级,以便在模糊的情况下选择具有最小优先级的函数。

我尝试制作一系列模板助手类,“代码”,P<0>P<1>,......,以便P<N>继承P<N+1>界。因此,如果有两个函数f(P<2>)f(P<4>),并且我调用f(P<0>),则会选择第一个函数。

它在实践中不起作用。经典的“干净”例子 “int / long”和“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>());
}

1 个答案:

答案 0 :(得分:7)

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

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

接下来,标签类型的自动扶梯只有在唯一的决胜局时才会有效。也就是说,每个其他参数都是等价的 - 除了tag参数。你的电话仍然含糊不清的原因是你最终得到的转换序列是:

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删除的超载,最终的决胜局就是标签。