【问题标题】:difference in static vs anonymous namespace for second pass name lookup during template instantiation模板实例化期间第二遍名称查找的静态与匿名名称空间的差异
【发布时间】:2021-09-25 12:20:01
【问题描述】:

我已经长期停止使用 static 来处理辅助函数,转而使用匿名命名空间,它的优势在于可以处理类型、变量和模板以及函数。

但是,当我用包装模板替换对它的调用时,没有找到一个函数,这让我感到惊讶。请参阅 https://godbolt.org/z/GrojceqGx 的代码,其中包含与我的项目匹配的编译器和选项。

#include <utility>
//#define WORKING

class C {};

template <typename Left, typename Right>
auto wrapper (Left&& left, Right&& right, const char* name)
{
    return foo (std::forward<Left>(left),std::forward<Right>(right));
}

#ifdef WORKING
static
void foo (C& left, int right)
{
    // compiles when using static function
}
#else
namespace {
void foo (C& left, int right)
{
    // fails to compile in anonymous namespace
}
}
#endif

void sample()
{
    C x;
    wrapper (x, 17, "call 1");
}

为什么wrapper 的实例化在static 时会看到foo,但在匿名命名空间中时却看不到?实例化点在这个翻译单元中,无论哪种方式都在同一个位置。

【问题讨论】:

  • 更新代码中的指令和注释以更清楚地显示差异,尽管这确实改变了问题中的代码与 Godbolt 上的代码。
  • 如果您将模板声明移到foo - live - godbolt.org/z/nbxf5nGsY 的声明之后,也可以使用

标签: c++ templates scope


【解决方案1】:

因为不管你信不信,匿名命名空间完全是另一个命名空间。而不是全局命名空间。

当您使用static 时,ADL 会找到foo。因为现在foo 正确地位于C 的关联命名空间(全局命名空间)中。

但它适用于内联匿名命名空间,即

inline namespace { }

因为 ADL 旨在与内联命名空间很好地配合使用。

【讨论】:

  • 真实示例中的命名空间还有更多内容:C 位于命名空间中,此 CPP 文件中的全局命名空间为 using it。但是输入inline 确实解决了这个问题。
猜你喜欢
  • 1970-01-01
  • 2017-01-06
  • 1970-01-01
  • 2010-09-14
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
  • 2014-02-18
相关资源
最近更新 更多