重载解析、定义函数和模板的顺序

Overload resolution, order of defined functions and templates

考虑以下代码片段:

template<class T>
std::enable_if_t<std::is_integral<T>::value, bool> func(T value) {
    std::cout << "T\n";
    return func(static_cast<int64_t>(value));
}

bool func(int64_t value) {
    std::cout << "int64_t\n";
    return true;
}

int main() {
    func(1);
}

导致无限递归。但是,交换这两个函数的定义顺序(如果 bool func(int64_t value) 在模板一之前定义)有助于避免此问题。

这是为什么?函数重载的顺序重要吗?

Does order of function overloads matter?

从某种意义上说,重载顺序确实很重要,如果在声明潜在重载之前调用重载集,则尚未声明的函数不会参与重载决议。

在函数调用之前声明的重载顺序无关紧要。

当编译器解析第一个函数(模板)时,它对 func 的第二个重载一无所知。解析是从源文件的顶部到底部完成的。

这就是您在使用符号之前需要进行符号声明的原因。这也意味着只要在顶部有一个 声明 of bool func(int64_t); 就可以解决你的问题。

Does order of function overloads matter?

不改变重载解析的结果,而是改变name lookup的结果;这发生在重载决议之前。

(强调我的)

For a name used in global (top-level namespace) scope, outside of any function, class, or user-declared namespace, the global scope before the use of the name is examined:

也就是说在模板化的func中调用func,只能找到自身(并加入到重载集中),非模板版本不予考虑完全没有。

如您所见,如果更改它们的声明顺序,将在以下重载决议中找到并考虑两个 func,并且选择非模板 func(如预期的那样) .