在重载解析期间,函数对象是否与常规函数处理不同?如果是,如何处理?
我遇到了以下情况,在这种情况下,将一个函数替换为等效可调用的函数对象会改变代码的含义:
#include <iostream>
namespace N
{
enum E { A, B };
void bar(E mode) { std::cout << "N::bar\n"; }
}
template <typename... Args>
void bar(Args&&... args) { std::cout << "global bar\n"; }
int main()
{
bar(N::A);
}
这里的输出是"N::bar"。到目前为止,一切都很好:ADL找到了N::bar,全局的bar和N::bar都是完全匹配的,但由于它不是一个模板,所以N::bar被优先选择。
但是如果我将全局的bar改为函数对象,像这样:
#include <iostream>
namespace N
{
enum E { A, B };
void bar(E mode) { std::cout << "N::bar\n"; }
}
struct S
{
template <typename... Args>
void operator()(Args&&... args) { std::cout << "global bar\n"; }
};
S bar;
int main()
{
bar(N::A);
}
输出现在是 "global bar",为什么会有这种差异?
bar
确实是函数调用表达式中的后缀表达式(没有函数作为操作数,但最终会调用一个函数!)。该注释说3.4.2不会改变“x(y)”的语法含义-如果它是函数调用,则无论3.4.2决定做什么,它仍然是函数调用。 - Johannes Schaub - litbbar
是一个对象,而作为对象的bar(x)
表示对该实例应用operator()
。虽然运算符的应用是函数调用,但它是一个成员函数调用,因此ADL不适用。 - David Rodríguez - dribeas