【问题标题】:ADL lookup inside a class (template) member function body类(模板)成员函数体内的 ADL 查找
【发布时间】: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


【解决方案1】:

First paragraph 在非限定名称查找中:

在 [basic.lookup.unqual] 中列出的所有情况下,范围是 按每个列表中列出的顺序搜索声明 各自的类别;名称查找在声明后立即结束 找到名称。

In particular,

对于X 类的成员,成员函数体中使用的名称[…],如下 成员的 declarator-id,应在其中之一中声明 以下方式:

名称的本地(重新)声明具有优先级,并隐藏所有外部声明。

【讨论】:

  • 啊!!然后 ADL 查找会再次找到函数成员,如果参数个数匹配,则添加到重载集合中,不是吗?
  • @Peregring-lk 是的,user::operator&lt;&lt; 将通过ref 的模板参数的关联命名空间找到。
  • user::operator&lt;&lt; 不是成员函数。此外,ref 是什么?还要考虑运算符语法:using std::operator&lt;&lt;; *this &lt;&lt; v;.
猜你喜欢
  • 2013-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 1970-01-01
  • 2011-02-26
  • 1970-01-01
  • 2012-01-22
相关资源
最近更新 更多