使用参数(const T&,const T&)或(const char(&)[N],const char(&)[M])重载模板的模糊调用

zhe*_*oli 9 c++ templates overloading c++11

对于以下代码:

#include <iostream>
using std::cout; using std::endl;

template <typename T>
int compare(const T&, const T&) {
    cout << __PRETTY_FUNCTION__ << endl;
    return 0;
}
template <size_t N, size_t M>
int compare(const char (&)[N], const char (&)[M]) {
    cout << __PRETTY_FUNCTION__ << endl;
    return 0;
}

int main(int argc, char *argv[]) {
    compare("hi", "is");
}
Run Code Online (Sandbox Code Playgroud)

当我编译代码时g++ -std=c++1y,它会抱怨:

error: call of overloaded ‘compare(const char [3], const char [3])’ is ambiguous
     compare("hi", "is");
Run Code Online (Sandbox Code Playgroud)

根据模板重载的规则,可行的功能是:

compare(const T&, const T&) with T = char [3]
compare(const char (&)[N], const char (&)[M]) with N = 3ul, M = 3ul
Run Code Online (Sandbox Code Playgroud)

它们都为呼叫提供了同样好的(即精确的)匹配.所以我应该检查哪一个更专业.

但根据我的有限知识,const T&比较普遍const char (&)[N].所以我认为这compare(const char (&)[N], const char (&)[M])更专业.但为什么这个电话含糊不清?

int*_*jay 10

第一个过载compare(const T&, const T&)强制两个参数都是相同的类型,而第二个过载不强制.所以在这方面,第一次过载更具体.

但是,第二次过载会强制两个参数都是char数组,因此在这方面更具体.

因此,既不能说过载比另一个更专业,结果就是模糊误差.

另一种看待它的方法是每个重载都可以接受另一个不输入的输入:只有第一个重载才会接受两个参数都是的调用int&.并且只有第二个重载将接受参数为char (&)[2]和的调用char (&)[3].

如果您将第二个重载更改为

template <size_t N> int compare(const char (&)[N], const char (&)[N])
Run Code Online (Sandbox Code Playgroud)

它将修复错误,因为这现在严格比第一次重载更具体.

  • @zhen这是一个不错的经验法则.但是exaxt定义将涉及标准和一些极端情况.理解它是一种偏序是很有意义的. (3认同)