【发布时间】:2017-10-28 16:33:15
【问题描述】:
struct B {};
struct C : B {};
void f(B){} // worse match than A::f<C>
struct A {
template<class T>
void f(T v) {
f(v); // #1
}
};
int main()
{
A{}.f(C{});
}
在#1 行中激活 ADL 查找非常简单
{
using ::f;
f(v);
}
我认为在没有using 指令的情况下使代码失败的规则是:
[basic.lookup.argdep]/3 设 X 为非限定查找产生的查找集,设 Y 为 由参数相关查找产生的查找集(定义为 如下)。如果 X 包含
- (3.1) 类成员的声明,或
- (3.2) 不是 using 声明的块范围函数声明,或
- (3.3) 既不是函数也不是函数模板的声明
那么 Y 为空。 [...]
因此,由于非 ADL 查找找到的对 f 的调用会找到类成员 A::f,因此 ADL 查找找到的重载将被丢弃。
哪条 C++ 规则允许忽略 3.1 中带有 using 声明的限制,以使上述代码编译?
我认为我完全误解了必须应用规则 [basic.lookup.argdep]/3 的上下文,或者我对名称的理解存在更大和隐藏的漏洞查找过程。
【问题讨论】:
-
嗯,你已经有一个 MCVE,但我真的认为你可以大大减少你的代码......
-
@Rakete1111 考虑到我需要,(A)成员函数,(B)具有用户定义类的用户命名空间,(C)至少两个重载同一个运算符,(D) 一个主函数。
-
它可能不长,但它有很多不必要的东西(比如从引用包装器继承,
ostreamable_with,...)IMO。 -
介意我为你减少代码吗?
-
@Peregring-lk 看你喜不喜欢,否则还原-
标签: c++ language-lawyer c++17 argument-dependent-lookup class-members