我有多个相同功能的重载。对于某些参数集,几个重载相同,我自然会得到一个“模糊过载”错误。我想在某种程度上定义这些函数的优先级,以便在模糊的情况下选择具有最小优先级的函数。
我尝试制作一系列模板助手类,“代码”,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>());
}
答案 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_a
,cond_b
和cond_c
不需要脱节,每种情况下的第一个参数都是相同的。因此,对于那些未被SFINAE删除的超载,最终的决胜局就是标签。