如果函数采用指向 class 的指针,则函数将完全脱离候选列表

Function falls completely off the candidate list if it takes a pointer to the class

为什么我不能有一个与成员函数同名的非成员函数,如果它也恰好采用指向 class 的指针?

这不编译:

struct FooConfig{ int value; };
struct BarConfig{ int value; };

class Api
{
    void configure(const FooConfig& cfg);
    void configure(const BarConfig& cfg);
};

// helper
static void configure(Api* self, int value)
{
    // Actual impl
}

void Api::configure(const FooConfig& cfg)
{
    configure(this, cfg.value);
}

void Api::configure(const BarConfig& cfg)
{
    configure(this, cfg.value);
}

Gcc 和 Clang 都在骗我,说没有名为 configure 的函数接受 2 个参数。

有趣的部分来了:

如果我只是用 self 指针重命名辅助函数,或者让它接受一个引用而不是指针,那么它突然就存在了,一切都很好。

AFAIK,与成员函数的巧合在名称查找中无关紧要。我在愚弄 C++ 吗?

尝试

::configure(this, cfg.value);

当尝试在成员函数中调用 configure 时,在 class 作用域(即成员函数)中找到名称 configure,然后 name lookup 停止,不会检查进一步的范围(全局范围);找不到全局 configure,它被成员函数隐藏了。

name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

作为解决方法,您可以将全局的指定为 ::configure(this, cfg.value);

在重载决议选择最佳可行函数之前,形成一组候选函数,具体匹配被调用者的名字。为此,使用名称查找过程。

表达式 configure(this, cfg.value) 是 class 成员函数范围内的 非限定调用 ,为此,名称查找过程将首先搜索声明在该功能块本身中(在第一次使用之前),如果没有找到,则遍历 class 及其基础 classes,只有当仍然没有找到时,它才会访问封闭的命名空间。也就是说,当使用这个搜索范围的有序层次结构时,它将在第一个声明处停止。

在上述过程的第 2 阶段,name loopkup 过程找到了 Api::configure 的两个过载,并形成了过载解析的候选集。由于两者都不接受两个参数,因此编译器正确诊断出错误。

为了强制使用全局命名空间中的函数,请使用 ::configure(this, cfg.value)。这表示应该为 configure.

的声明搜索哪个命名空间

If I [...] make it take a reference instead of pointer, then it suddenly comes to existence, and all is well.

这是不可能的,因为这不会影响名称查找过程。但是,更改名称确实如此。