【问题标题】:Why doesn't ADL work with functions defined outside of a namespace?为什么 ADL 不适用于在命名空间之外定义的函数?
【发布时间】:2021-02-25 14:27:13
【问题描述】:

我知道下面示例中的编译器将执行函数 First::fun(),因为 Argument-Dependent name Lookup (ADL)/Koenig lookup 并且为了执行 Second::fun() 这需要在 @ 中显式调用987654324@函数。

#include <iostream>
using namespace std;

namespace First
{
    enum Enum
    {
        FIRST
    };

    void fun(First::Enum symbol)
    {
        cout << "First fun\n";
    }
}

namespace Second
{
    void fun(First::Enum symbol)
    {
        cout << "Second fun\n";
    }
}

int main()
{
    fun(First::FIRST);  // Calls First::fun()
}

但是,当在命名空间之外添加另一个函数 fun()(参见下面的代码)并在没有前缀命名空间的情况下调用 fun() 时,编译器会出现歧义错误。命名空间内的函数仍然可以通过显式前缀命名空间来调用,但fun() 是无法访问的。当没有显式调用时,为什么编译器不喜欢命名空间之外的函数?避免这种行为是否有特定原因?

// ^ Namespaces are still here

fun(First::Enum symbol)
{
    cout << "No namespace fun\n";
}    

int main()
{
    fun(First::FIRST);  // Doesn't compile: ambiguity!
}

编辑

正如Yksisarvinen 正确指出的那样,全局fun() 仍然可以通过以全局命名空间为前缀来调用:::fun(First::FIRST);

但是,这仍然给我留下了一个问题:为什么编译器在模棱两可的调用中不喜欢全局 fun()

【问题讨论】:

  • 注意:全局 fun 与命名空间相同,您需要在其前面加上全局名称:::fun(First::FIRST)
  • 哦,谢谢!这实际上已经回答了这个问题。我不知道这一点!
  • 作为附加的元问题,我如何将我的问题标记为现在已解决?我无法将评论标记为解决方案 afaik
  • 在那种情况下,我会留下我的问题,希望有人可以回答这部分,因为我也对此感兴趣。
  • “这就是语言的工作原理”并不是关于语言如何工作的问题的建设性答案。

标签: c++ argument-dependent-lookup


【解决方案1】:

为什么编译器在模棱两可的调用中不喜欢全局fun()

全局fununqualified name lookup找到,First::funADL找到,都放入了重载集,重载解析不能选择一个。

除了通常的非限定名称查找所考虑的范围和名称空间之外,还会在其参数的名称空间中查找这些函数名称。

【讨论】:

  • 如果由非限定查找生成的查找集包含在块范围内声明的函数,则 ADL 不会继续。全局命名空间不是块作用域吗?究竟什么是块作用域?
  • @NathanPierson 块范围基本上是{} 内的任何东西。所以this 是明确的,因为funmain 中声明。
  • @cigien Ahhh,谢谢!所以声明是在块范围内,它会在全局命名空间范围内寻找定义? (另外,一个小提示,炫耀块范围的编辑使评论无效,说它调用First::fun。)
  • @cigien 命名空间不算作块作用域。
  • @NathanPierson 是的。确实,我没有看到评论出错了;)错误的 cmets 比错误的代码更难捕捉 :(
猜你喜欢
  • 2012-09-26
  • 1970-01-01
  • 2014-09-27
  • 2018-11-17
  • 2017-12-27
  • 2011-03-21
  • 2013-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多