Boost C++ 库

...世界上最受尊敬和专家设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu, C++ 编码标准

Boost.MultiIndex 编译器细节



Boost.MultiIndex 利用了一些 C++11 的功能,但也能够在良好的 C++03 兼容环境中正常工作。我们列出了一些可能的限制,以及可行的解决方法。

目录

移动语义

Boost.MultiIndex 使用 Boost.Move 来支持没有右值引用的编译器。在这种情况下,要利用 multi_index_container<Value> 的功能来提高插入和处理仅可移动元素的效率,需要对 Value 进行适当的处理。

分配器感知

在 C++11 之前的编译器或缺少适当的 分配器感知 机制(基本上是 std::allocator_traits)的有缺陷环境中,Boost.MultiIndex 的行为就像所有分配器的 std::allocator_traits<allocator_type>::propagate_on_container_*::value 均为 false

Emplace 函数

在不支持可变参数模板的编译器中,Boost.MultiIndex 的 emplace 函数通过接受最多 BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS 个构造参数来模拟这个缺失的功能,这些参数使用 Boost.Move 在内部转发:在这种情况下,只允许使用常量左值引用和右值作为构造参数。

BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS 的默认值为 5,用户可以全局定义为不同的值。

初始化列表

在缺少 std::initializer_list 的情况下,无法提供透明的模拟功能:可以考虑使用 Boost.Assign 作为替代方案。

元组

在库接口中使用 std::tuple 的任何地方,都可以使用 boost::tuple 来代替。但是,反过来不行。

符号名称长度的缩减

multi_index_container 实例化生成的类型通常会产生很长的符号名称,有时会超出某些编译器的内部限制。有几种技术可以缩短生成的符号名称:这些技术还有一个好处是,生成的错误消息更具可读性。

参数数量上限的限制

类模板 indexed_bytagcomposite_key 接受可变数量的参数,其最大数量受内部宏的限制。即使未使用的参数也会影响最终类型,因此手动调整相应的宏可以适度减少符号名称。

限制 Boost.MultiIndex 的某些类模板的最大参数数量。
类模板 限制宏 默认值
 indexed_by   BOOST_MULTI_INDEX_LIMIT_INDEXED_BY_SIZE  20
 tag   BOOST_MULTI_INDEX_LIMIT_TAG_SIZE  20
 composite_key   BOOST_MULTI_INDEX_LIMIT_COMPOSITE_KEY_SIZE  10

类型隐藏

考虑 multi_index_container 的典型实例化

typedef multi_index_container<
  employee,
  indexed_by<
    ordered_unique<identity<employee> >,
    ordered_non_unique<member<employee,std::string,&employee::name> >,
    ordered_unique<member<employee,int,&employee::ssnumber> >
  >
> employee_set;

然后,例如,类型 employee_set::nth_index<0>::type 在 GCC 中解析为以下内容

boost::multi_index::detail::ordered_index<
  boost::multi_index::identity<employee>,
  std::less<employee>,
  boost::multi_index::detail::nth_layer<
    1, employee,
    boost::multi_index::indexed_by<
      boost::multi_index::ordered_unique<
        boost::multi_index::identity<employee>, mpl_::na, mpl_::na
      >,
      boost::multi_index::ordered_non_unique<
        boost::multi_index::member<employee, std::string, &employee::name>,
        mpl_::na, mpl_::na
      >,
      boost::multi_index::ordered_unique<
        boost::multi_index::member<employee, int, &employee::ssnumber>,
        mpl_::na, mpl_::na
      >,
      mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
      mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na,
      mpl_::na, mpl_::na, mpl_::na, mpl_::na, mpl_::na
    >,
    std::allocator<employee>
  >,
  boost::mpl::vector0<mpl_::na>,
  boost::multi_index::detail::ordered_unique_tag
>

可以看出,类型名称的很大一部分是由 indexed_by<...> 部分贡献的,这只不过是 employee_set 定义中提供的索引说明符列表的扩展版本。我们可以通过将它封装到另一个名称较短的构造中来防止这个很长的名称出现在最终类型中

// reducing symbol names through type hiding
// type hide the index specifier list within employee_set_indices

struct employee_set_indices:
  indexed_by<
    ordered_unique<identity<employee> >,
    ordered_non_unique<member<employee,std::string,&employee::name> >,
    ordered_unique<member<employee,int,&employee::ssnumber> >
  >
{};

typedef multi_index_container<
  employee,
  employee_set_indices
> employee_set;

employee_set_indices 在所有方面都像传统的 typedef 一样工作,只有一个细节:它的名称没有明确包含 indexed_by 实例化中包含的信息。应用此技术后,employee_set::nth_index<0>::type 现在变为

boost::multi_index::detail::ordered_index<
  boost::multi_index::identity<employee>,
  std::less<employee>,
  boost::multi_index::detail::nth_layer<
    1, employee,
    employee_set_indices,
    std::allocator<employee>
  >,
  boost::mpl::vector0<mpl_::na>,
  boost::multi_index::detail::ordered_unique_tag
>

它比原来的短得多,而且更容易被人阅读。如果我们没有将 employee_set_indices 定义为 indexed_by<...> 的派生 struct,而是将其定义为 typedef,则类型隐藏将不起作用:typedef 是语法别名,通常在编译器进行任何进一步的类型处理之前会被扩展。

类型隐藏技术也可以应用于 composite_key 实例化,这通常会对符号名称长度产生很大影响。

旧版编译器

Boost.MultiIndex 对旧版编译器的支持并未得到积极维护,因此如果您碰巧使用旧环境,则可能需要使用该库的早期版本。下表提供了一些旧版编译器以及已知可与其配合使用的最新版 Boost.MultiIndex(通常具有相应编译器细节部分中所述的限制。)如果您成功地将其中一个与比此处所述更新版本的 Boost.MultiIndex 配合使用,请报告回来,以便更新信息。

对旧版编译器的支持。
编译器 已知的最新
兼容版本
日期
Borland C++ Builder 6.4 至 2006,CodeGear C++Builder 2010 从未与 Boost.MultiIndex 兼容
适用于 Windows 的 Comeau C/C++ 4.3.10.1(VC++ 9.0 后端) Boost 1.38 2009 年 2 月
适用于 Tru64 UNIX 的 Compaq C++ 6.5-042 至 7.1-006 Boost 1.38 2009 年 2 月
GCC 3.2 至 3.4 Boost 1.41 2009 年 11 月
适用于 HP-UX IA64 的 HP aC++ A.06.12 至 A.06.17 Boost 1.38 2009 年 2 月
适用于 HP-UX PA-RISC 的 HP aC++ A.03.80 至 A.03.85 Boost 1.38 2009 年 2 月
适用于 AIX 的 IBM VisualAge C++ V6.0 Boost 1.33.1 2006 年 12 月
适用于 AIX 的 IBM XL C/C++ V9.0 至 V10.1 Boost 1.41 2009 年 11 月
适用于 Linux 的 Intel C++ 编译器 8.1 至 11.1 Boost 1.41 2009 年 11 月
适用于 Mac OS 的 Intel C++ 编译器 9.1 至 11.0 Boost 1.41 2009 年 11 月
适用于 Windows 32 位的 Intel C++ 编译器 8.0 至 11.1 Boost 1.41 2009 年 11 月
适用于 Windows 64 位的 Intel C++ 编译器 10.0 至 11.11 Boost 1.41 2009 年 11 月
Metrowerks CodeWarrior 8.3 Boost 1.36 2008 年 8 月
Metrowerks CodeWarrior 9 至 9.5 Boost 1.34.1 2007 年 7 月
Microsoft Visual C++ 6.0 Service Pack 5 Boost 1.36 2008 年 8 月
Microsoft Visual C++ 7.0 Boost 1.35 2008 年 3 月
适用于 Solaris 的 Sun Studio 10 至 12 Update 1 Boost 1.41 2009 年 11 月




修订于 2020 年 1 月 25 日

© 版权所有 2003-2020 Joaquín M López Muñoz。根据 Boost 软件许可证,版本 1.0 分发。(请参阅随附文件 LICENSE_1_0.txt 或复制于 https://boost.ac.cn/LICENSE_1_0.txt