C++ 模块中命名空间内的“using”不限于命名空间

Ric*_*ish 18 c++ c++20 c++-modules

给定以下模块example

module;

#include "example.h" // `namespace cxx { struct example {}; }`

export module example;

export namespace cxx::containers
{
    using cxx::example;
}
Run Code Online (Sandbox Code Playgroud)

cxx::containers::examplecxx::example也可以从我只希望cxx::containers::example出现的地方访问。

import example;

int main()
{
    auto v1 = cxx::containers::example();
    auto v2 = cxx::example();
}
Run Code Online (Sandbox Code Playgroud)

cxx::example即使我只在命名空间内使用它cxx::containers::example并且#include全局module;片段中的指令应该本地化到它们的模块,但它仍然可见的原因是什么?

Dav*_*ing 7

严格的答案(“可见的原因cxx::example”)是它是一个MSVC bug:未导出 的声明cxx::example,因此在相关模块外部通过名称查找找不到它([basic.lookup.general]/ 2.3,除非在某些涉及依赖 ADL\xc2\xa0([basic.lookup.argdep]/4)) 的情况下。

\n

自 C++20 发布以来,using-declaration的措辞已进行了重大修改,以澄清原始声明和新声明之间的关系。using 声明不是原始实体或 typedef 的重新声明(这就是它可以单独导出的原因);相反,名称查找将using -declarator替换为其引用的声明\xc2\xa0([basic.lookup.general]/3)。using声明优先因为它是导出\xc2\xa0(/2.3);其自身的声明没有,因此找不到\xc2\xa0([basic.lookup.qual.general]/3, [class.member.lookup]/1, 以及 [basic.lookup.一般]/3) 除非通过上述替换。cxx::containers::example maincxx::example

\n

唯一相关性较远的using 指令的措辞也已更改(作为追溯缺陷报告),以通常允许导出的using 指令​​s\xc2\xa0([basic.lookup.unqual]/1, [namespace.质量]/1,[模块.接口]/4)。(它们可能已经以标头单元导出。)当然,如果您不\xe2\x80\x99t导出它们,您可以在模块中使用它们只是为了方便,而不会影响您的客户端!

\n

  • @RickySpanish:我的意思是两者都使用“using”,但在机制上有很大不同;您没有询问“使用命名空间”,但人们似乎也想查看它的相应信息,特别是因为最初不可能导出它们,除非隐式地将它们放入标头单元中。最后一点实际上是对非导出 *using-directive* 的认可,它的便利性吸引了很多人,而且没有最糟糕的副作用。 (2认同)