提问人:md1357 提问时间:3/25/2022 更新时间:12/21/2022 访问量:279
为什么标准库类型可以访问在“std”中,尽管它们嵌套在实现定义的命名空间中?
Why are standard library types accessible inside `std` despite being nested in implementation-defined namespaces?
问:
我正在浏览 GCC 11.2 标头的实现(可以在这里找到),我注意到一些我正在努力理解的东西。这是标题(希望)只遗漏了重要的部分:<optional>
#ifndef _GLIBCXX_OPTIONAL
#define _GLIBCXX_OPTIONAL 1
#pragma GCC system_header
#if __cplusplus >= 201703L
/* Includes of various internal and library headers */
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus == 201703L
# define __cpp_lib_optional 201606L
#else
# define __cpp_lib_optional 202106L
#endif
/* Implementation */
template<typename _Tp>
class optional;
/* Implementation */
template<typename _Tp>
class optional: /* Implementation */
{ /* Implementation */ };
/* Implementation */
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++17
#endif // _GLIBCXX_OPTIONAL
我发现并分别扩展到 和 (之前没有)。_GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX_END_NAMESPACE_VERSION
namespace __8 {
}
inline
namespace __8
因此,它看起来实际上是在非内联命名空间中定义的,但尽管如此,我显然可以在我的程序中引用,就好像它直接位于 .std::optional
std::__8
std::optional
std
我认为没有任何有效的指令,首先是因为我没有找到任何指令,其次是因为应该允许它专门用于自定义类型,而无需打开实现定义的命名空间([namespace.std#2],[temp.spec.partial.general#6])。using
std::optional
宏扩展到 ,但我认为它不相关(文档)。我在文档的编译指示列表中找不到。_GLIBCXX_VISIBILITY(default)
__attribute__ ((__visibility__ ("default")))
system_header
因此,我不明白为什么我应该能够引用可选类 as 和 not .我在这里错过了什么?std::optional
std::__8::optional
答:
定义这些宏的 in libstdc++ 最初也声明了 version 命名空间,如下所示:c++config
inline
// Defined if inline namespaces are used for versioning.
#define _GLIBCXX_INLINE_VERSION
// Inline namespace for symbol versioning.
#if _GLIBCXX_INLINE_VERSION
# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 {
# define _GLIBCXX_END_NAMESPACE_VERSION }
namespace std
{
inline _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201402L
inline namespace literals {
inline namespace chrono_literals { }
inline namespace complex_literals { }
inline namespace string_literals { }
#if __cplusplus > 201402L
inline namespace string_view_literals { }
#endif // C++17
}
#endif // C++14
_GLIBCXX_END_NAMESPACE_VERSION
}
一旦 a 被声明,它总是 .例如:namespace
inline
inline
namespace A {
inline namespace B {
struct X { };
}
}
namespace A {
namespace B {
struct Y { };
}
}
A::X x; // ok
A::Y y; // still ok
即使 GCC 没有,Clang 也警告了这一点,但它也是一个系统标头,所以即使 GCC 对它有所影响也没关系。
不过,不知道为什么不直接添加到宏定义中。我们可能还没有到每个标头额外的 7 个字符对编译时间造成重大损害的地步?inline
评论
c++config
config.h
std::__8::vector
评论