__vector_base_common 是怎么回事?
What is going on with __vector_base_common?
我想看看 C++ 向量是如何制作的。我找到了这个,
实现是 LLVM 编译器 https://llvm.org/svn/llvm-project/libcxx/trunk/src/vector.cpp appleclang
src/vector.cpp:
#include "vector"
_LIBCPP_BEGIN_NAMESPACE_STD
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
_LIBCPP_END_NAMESPACE_STD
实施https://llvm.org/svn/llvm-project/libcxx/trunk/include/vector appleclang LLVM。
include/vector:
// .. deleted code
template <bool>
class __vector_base_common
{
protected:
_LIBCPP_ALWAYS_INLINE __vector_base_common() {}
_LIBCPP_NORETURN void __throw_length_error() const;
_LIBCPP_NORETURN void __throw_out_of_range() const;
};
template <bool __b>
void
__vector_base_common<__b>::__throw_length_error() const
{
_VSTD::__throw_length_error("vector");
}
template <bool __b>
void
__vector_base_common<__b>::__throw_out_of_range() const
{
_VSTD::__throw_out_of_range("vector");
}
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __vector_base_common<true>)
// .. deleted code
template <class _Tp, class _Allocator>
class __vector_base
: protected __vector_base_common<true>
// .. deleted code
class _LIBCPP_TEMPLATE_VIS vector
: private __vector_base<_Tp, _Allocator>
// .. deleted code
我有很多关于矢量是如何制作的问题。即使问一个都感觉很尴尬。但是..为什么 __vector_base_common 采用 bool 模板参数?它似乎没有使用它,我验证了仅在代码中使用的是 __vector_base_common<true>
,未使用 false
值。
编辑: 有多个与此相关的建议 vector<bool>
。仅使用了上述 bool 参数的一种特化 (true
)。这就是 vector special 的样子
template <class _Allocator>
class _LIBCPP_TEMPLATE_VIS vector<bool, _Allocator>
: private __vector_base_common<true>
private 与 protected 之间的区别...这是对不需要那些抛出成员函数的 vector 的 space 优化吗?我仍然有疑问为什么 __vector_base_common
需要一个模板参数。这个 C++ 模式有名字吗?
这是一个实现技巧,因此库可以仅用作 headers,或者具有预编译部分。
vector
的一些成员函数根本不依赖于模板参数;具体来说,是抛出异常的辅助函数。因此可以(不像那些依赖于模板参数的部分)将它们编译一次并放在一个共享库中。例如,这就是在 MacOS 上发生的情况。
另一方面,在没有使用 OS 分发库的平台上,如果用户不必分发共享库,而是可以使用库作为 header-only,即包含 <vector>
并完成它,而不必在构建中向链接器调用添加标志。
这意味着您需要这些函数的代码在 header 中可用,但如果您使用共享库变体,则在使用 header 时实际上不应编译它.
这里介绍的技巧是实现这一目标的一种方法。首先,将实现放入模板中,这样它就可以存在于 header 中而不会产生多个定义错误。有问题的模板只有一个虚拟参数;重要的是它是一个模板,而不是它有任何特定的参数。这是 header-only 个图书馆常用的技术。
现在您可以使用库 header-only。但是如果你想使用共享库变体,你实际上需要提前编译代码并为库用户抑制代码生成。为此可以使用显式模板实例化。
所以你在 header:
中放置了一个外部模板声明
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __vector_base_common<true>;
因此 header 现在包含一个明确的专业化声明,抑制模板成员的代码生成。
然后你拿一个源文件,放入显式实例化,并将它编译成一个共享库。
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
现在您已经涵盖了共享库的使用,但是您破坏了使用库的能力 header-only。要取回它,您需要根据库的使用模式将 extern template
声明设为可选。因此,您将声明包装在一个定义取决于模式的宏中:
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __vector_base_common<true>)
#ifdef _LIBCPP_DISABLE_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...)
#endif
#ifndef _LIBCPP_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#endif
因此,如果您处于 header-only 模式(_LIBCPP_DISABLE_EXTERN_TEMPLATE
已定义),声明将消失。如果您处于共享库模式,声明就在那里,防止代码生成。
vector<bool>
私有地从 __vector_base_common
派生的原因是因为它没有任何派生的 类 本身需要访问 throw 助手。 vector<T>
派生自 __vector_base<T>
,__vector_base<T>
又派生自 __vector_base_common
;所以 vector<T>
要访问 __vector_base_common
成员,__vector_base<T>
必须派生自 __vector_base_common
作为 protected
.
我想看看 C++ 向量是如何制作的。我找到了这个, 实现是 LLVM 编译器 https://llvm.org/svn/llvm-project/libcxx/trunk/src/vector.cpp appleclang
src/vector.cpp:
#include "vector"
_LIBCPP_BEGIN_NAMESPACE_STD
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
_LIBCPP_END_NAMESPACE_STD
实施https://llvm.org/svn/llvm-project/libcxx/trunk/include/vector appleclang LLVM。
include/vector:
// .. deleted code
template <bool>
class __vector_base_common
{
protected:
_LIBCPP_ALWAYS_INLINE __vector_base_common() {}
_LIBCPP_NORETURN void __throw_length_error() const;
_LIBCPP_NORETURN void __throw_out_of_range() const;
};
template <bool __b>
void
__vector_base_common<__b>::__throw_length_error() const
{
_VSTD::__throw_length_error("vector");
}
template <bool __b>
void
__vector_base_common<__b>::__throw_out_of_range() const
{
_VSTD::__throw_out_of_range("vector");
}
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __vector_base_common<true>)
// .. deleted code
template <class _Tp, class _Allocator>
class __vector_base
: protected __vector_base_common<true>
// .. deleted code
class _LIBCPP_TEMPLATE_VIS vector
: private __vector_base<_Tp, _Allocator>
// .. deleted code
我有很多关于矢量是如何制作的问题。即使问一个都感觉很尴尬。但是..为什么 __vector_base_common 采用 bool 模板参数?它似乎没有使用它,我验证了仅在代码中使用的是 __vector_base_common<true>
,未使用 false
值。
编辑: 有多个与此相关的建议 vector<bool>
。仅使用了上述 bool 参数的一种特化 (true
)。这就是 vector special 的样子
template <class _Allocator>
class _LIBCPP_TEMPLATE_VIS vector<bool, _Allocator>
: private __vector_base_common<true>
private 与 protected 之间的区别...这是对不需要那些抛出成员函数的 vector 的 space 优化吗?我仍然有疑问为什么 __vector_base_common
需要一个模板参数。这个 C++ 模式有名字吗?
这是一个实现技巧,因此库可以仅用作 headers,或者具有预编译部分。
vector
的一些成员函数根本不依赖于模板参数;具体来说,是抛出异常的辅助函数。因此可以(不像那些依赖于模板参数的部分)将它们编译一次并放在一个共享库中。例如,这就是在 MacOS 上发生的情况。
另一方面,在没有使用 OS 分发库的平台上,如果用户不必分发共享库,而是可以使用库作为 header-only,即包含 <vector>
并完成它,而不必在构建中向链接器调用添加标志。
这意味着您需要这些函数的代码在 header 中可用,但如果您使用共享库变体,则在使用 header 时实际上不应编译它.
这里介绍的技巧是实现这一目标的一种方法。首先,将实现放入模板中,这样它就可以存在于 header 中而不会产生多个定义错误。有问题的模板只有一个虚拟参数;重要的是它是一个模板,而不是它有任何特定的参数。这是 header-only 个图书馆常用的技术。
现在您可以使用库 header-only。但是如果你想使用共享库变体,你实际上需要提前编译代码并为库用户抑制代码生成。为此可以使用显式模板实例化。
所以你在 header:
中放置了一个外部模板声明extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __vector_base_common<true>;
因此 header 现在包含一个明确的专业化声明,抑制模板成员的代码生成。
然后你拿一个源文件,放入显式实例化,并将它编译成一个共享库。
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __vector_base_common<true>;
现在您已经涵盖了共享库的使用,但是您破坏了使用库的能力 header-only。要取回它,您需要根据库的使用模式将 extern template
声明设为可选。因此,您将声明包装在一个定义取决于模式的宏中:
_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __vector_base_common<true>)
#ifdef _LIBCPP_DISABLE_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...)
#endif
#ifndef _LIBCPP_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#endif
因此,如果您处于 header-only 模式(_LIBCPP_DISABLE_EXTERN_TEMPLATE
已定义),声明将消失。如果您处于共享库模式,声明就在那里,防止代码生成。
vector<bool>
私有地从 __vector_base_common
派生的原因是因为它没有任何派生的 类 本身需要访问 throw 助手。 vector<T>
派生自 __vector_base<T>
,__vector_base<T>
又派生自 __vector_base_common
;所以 vector<T>
要访问 __vector_base_common
成员,__vector_base<T>
必须派生自 __vector_base_common
作为 protected
.