gpt4 book ai didi

c++ - __vector_base_common 是怎么回事?

转载 作者:太空狗 更新时间:2023-10-29 21:33:46 27 4
gpt4 key购买 nike

我想看看 C++ vector 是如何制作的。我找到了这个,实现是 LLVM 编译器 https://llvm.org/svn/llvm-project/libcxx/trunk/src/vector.cpp苹果声

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。

包含/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 是如何制作的问题。即使问一个都感觉很尴尬......但是......为什么 __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 不需要那些抛出成员函数的空间优化吗?我仍然有疑问为什么 __vector_base_common需要一个模板参数。这个 C++ 模式有名字吗?

最佳答案

这是一个实现技巧,因此该库可以仅用作 header ,也可以具有预编译部分。

一些vector的成员函数根本不依赖于模板参数;具体来说,是抛出异常的辅助函数。因此可以(不像那些依赖于模板参数的部分)将它们编译一次并放在一个共享库中。例如,这就是 MacOS 上发生的情况。

另一方面,在库未随操作系统分发的平台上,如果用户不必分发共享库,而是可以将库作为仅 header 使用,对用户来说会更方便,即包括 <vector>并完成它,而不必在构建中向链接器调用添加标志。

这意味着您需要这些函数的代码在 header 中可用,但如果您使用共享库变体,则在使用 header 时实际上不应对其进行编译。

此处介绍的技巧是实现该目标的一种方法。首先,将实现放入模板中,这样它就可以存在于标题中而不会产生多个定义错误。有问题的模板只有一个虚拟参数;重要的是它是一个模板,而不是它有任何特定的参数。这是仅 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 的能力。要取回它,您需要制作 extern template声明可选,取决于库的使用模式。因此,您将声明包装在一个宏中,该宏的定义取决于模式:

_LIBCPP_EXTERN_TEMPLATE(class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __vector_base_common<true>)

这个宏是conditionally defined :

#ifdef _LIBCPP_DISABLE_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...)
#endif

#ifndef _LIBCPP_EXTERN_TEMPLATE
#define _LIBCPP_EXTERN_TEMPLATE(...) extern template __VA_ARGS__;
#endif

因此,如果您处于仅 header 模式(定义了 _LIBCPP_DISABLE_EXTERN_TEMPLATE),声明就会消失。如果您处于共享库模式,声明就在那里,防止代码生成。


原因vector<bool>私有(private)派生自__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++ - __vector_base_common 是怎么回事?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50050659/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com