Boost C++ 库

...世界上最受推崇和专业设计的 C++ 库项目之一。 Herb SutterAndrei Alexandrescu,《C++ 编码标准

简介

C++ 标准模板库 STL 作为 C++ 标准库的一部分,为处理不同类型容器的算法提供了一个框架。然而,普通数组不提供 STL 容器的接口(尽管它们提供了 STL 容器的迭代器接口)。

作为普通数组的替代品,STL 提供了类 std::vector。然而,std::vector<> 提供了动态数组的语义。因此,它管理数据以便能够更改元素数量。这在只需要静态大小的数组时会导致一些开销。

Matthew H. Austern 在他的著作《泛型编程与 STL》中,介绍了一个用于静态大小的普通数组的有用包装类,名为 block。它比普通数组更安全,并且性能不差。Bjarne Stroustrup 在《C++ 编程语言》第三版中,介绍了一个类似的类,名为 c_array,我 (Nicolai Josuttis) 在我的著作《C++ 标准库——教程与参考》中对其进行了略微修改,名为 carray。这是这些方法的精髓,并融入了来自 Boost 的许多反馈。

在考虑了不同的名称之后,我们决定将此类简单地命名为 array

请注意,建议此类作为下一个技术报告的一部分,这将扩展 C++ 标准(参见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2003/n1548.htm)。

更新:std::array(从 C++11 开始)是 C++ 标准的一部分。boost::arraystd::array 之间的差异很小。如果您正在使用 C++11,则应考虑使用 std::array 而不是 boost::array

array 满足“可逆容器”的大部分但并非全部要求(参见 C++ 标准第 23.1 节,[lib.container.requirements])。array 不是可逆 STL 容器的原因是因为

  • 没有提供构造函数。

  • 元素可能具有不确定的初始值(请参阅名为“设计原理”的章节)。

  • swap() 没有恒定复杂度。

  • size() 始终是常量,基于类型的第二个模板参数。

  • 容器不提供分配器支持。

它不满足“序列”的要求(参见 C++ 标准第 23.1.1 节,[lib.sequence.reqmts]),除非

  • 提供了 front()back()

  • 提供了 operator[]at()

修订历史

1.88.0 版本中的更改

  • 将文档转换为 AsciiDoc (Christian Mazakas)。

  • 根据需要添加了 noexceptconstexpr

  • 将过时的函数标记为已弃用。

  • 删除了过时的编译器解决方法。

  • 更改了 array<T, 0>::begin()cbegin()end()cend() 以返回 nullptr,从而启用 constexpr。这与 std::array 的行为相匹配。

  • 删除了本地 hash_value 重载;boost::hash 本机支持类似数组的类型。

  • 现在可以使用 = {{}} 初始化 array<T, 0>

  • 添加了 operator<=>

  • 添加了 to_array

参考

头文件 <boost/array.hpp>

namespace boost {

  template<typename T, std::size_t N> class array;

  template<typename T, std::size_t N>
    void swap(array<T, N>&, array<T, N>&);

  template<typename T, std::size_t N>
    constexpr bool operator==(const array<T, N>&, const array<T, N>&);
  template<typename T, std::size_t N>
    constexpr bool operator!=(const array<T, N>&, const array<T, N>&);

  template<typename T, std::size_t N>
    constexpr bool operator<(const array<T, N>&, const array<T, N>&);
  template<typename T, std::size_t N>
    constexpr bool operator>(const array<T, N>&, const array<T, N>&);
  template<typename T, std::size_t N>
    constexpr bool operator<=(const array<T, N>&, const array<T, N>&);
  template<typename T, std::size_t N>
    constexpr bool operator>=(const array<T, N>&, const array<T, N>&);

  template<typename T, std::size_t N>
    constexpr auto operator<=>(const array<T, N>&, const array<T, N>&);

  template<std::size_t Idx, typename T, std::size_t N>
    constexpr T& get(array<T, N>&) noexcept;
  template<std::size_t Idx, typename T, std::size_t N>
    constexpr const T& get(const array<T, N>&) noexcept;

  template<class T, std::size_t N>
    constexpr array<T, N> to_array( T const (&)[N] );
  template<class T, std::size_t N>
    constexpr array<T, N> to_array( T (&&)[N] );
  template<class T, std::size_t N>
    constexpr array<T, N> to_array( T const (&&)[N] );
}

类模板 array

概要

// In header: <boost/array.hpp>

template<typename T, std::size_t N>
class array {
public:

  // types

  typedef T                                     value_type;
  typedef T*                                    iterator;
  typedef const T*                              const_iterator;
  typedef std::reverse_iterator<iterator>       reverse_iterator;
  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
  typedef T&                                    reference;
  typedef const T&                              const_reference;
  typedef std::size_t                           size_type;
  typedef std::ptrdiff_t                        difference_type;

  // static constants

  static const size_type static_size = N;

  // construct/copy/destroy

  template<typename U> array& operator=(const array<U, N>&);

  // iterator support

  constexpr iterator begin() noexcept;
  constexpr const_iterator begin() const noexcept;
  constexpr const_iterator cbegin() const noexcept;

  constexpr iterator end() noexcept;
  constexpr const_iterator end() const noexcept;
  constexpr const_iterator cend() const noexcept;

  // reverse iterator support

  reverse_iterator rbegin() noexcept;
  const_reverse_iterator rbegin() const noexcept;
  const_reverse_iterator crbegin() const noexcept;

  reverse_iterator rend() noexcept;
  const_reverse_iterator rend() const noexcept;
  const_reverse_iterator crend() const noexcept;

  // capacity

  static constexpr size_type size() noexcept;
  static constexpr bool empty() noexcept;
  static constexpr size_type max_size() noexcept;

  // element access

  constexpr reference operator[](size_type);
  constexpr const_reference operator[](size_type) const;

  constexpr reference at(size_type);
  constexpr const_reference at(size_type) const;

  constexpr reference front();
  constexpr const_reference front() const;

  constexpr reference back();
  constexpr const_reference back() const;

  constexpr T* data() noexcept;
  constexpr const T* data() const noexcept;

  T* c_array() noexcept; // deprecated

  // modifiers

  swap(array<T, N>&);

  constexpr void fill(const T&);
  void assign(const T&); // deprecated

  // public data members
  T elems[N];
};

构造/复制/销毁

template<typename U> array& operator=(const array<U, N>& other);
效果

对于 [0..N) 中的每个 i,执行 elems[i] = other.elems[i];


迭代器支持

constexpr iterator begin() noexcept;
constexpr const_iterator begin() const noexcept;
constexpr const_iterator cbegin() const noexcept;
返回

data().


constexpr iterator end() noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cend() const noexcept;
返回

data() + size().


反向迭代器支持

reverse_iterator rbegin() noexcept;
返回

reverse_iterator(end()).


const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator crbegin() const noexcept;
返回

const_reverse_iterator(end()).


reverse_iterator rend() noexcept;
返回

reverse_iterator(begin()).


const_reverse_iterator rend() const noexcept;
const_reverse_iterator crend() const noexcept;
返回

const_reverse_iterator(begin()).


容量

static constexpr size_type size() noexcept;
返回

N.


static constexpr bool empty() noexcept;
返回

N == 0.


static constexpr size_type max_size() noexcept;
返回

N.


元素访问

constexpr reference operator[](size_type i);
constexpr const_reference operator[](size_type i) const;
要求

i < N.

返回

elems[i].

抛出

无。


constexpr reference at(size_type i);
constexpr const_reference at(size_type i) const;
返回

elems[i].

抛出

如果 i >= N,则抛出 std::out_of_range 异常。


constexpr reference front();
constexpr const_reference front() const;
要求

N > 0.

返回

elems[0].

抛出

无。


constexpr reference back();
constexpr const_reference back() const;
要求

N > 0.

返回

elems[N-1].

抛出

无。


constexpr T* data() noexcept;
constexpr const T* data() const noexcept;
返回

elems.


T* c_array() noexcept; // deprecated
返回

data().

备注

此函数已弃用。请改用 data()


修改器

void swap(array<T, N>& other);
效果

std::swap(elems, other.elems).

复杂度

线性于 N。


void fill(const T& value);
效果

对于 [0..N) 中的每个 i,执行 elems[i] = value;


void assign(const T& value); // deprecated
效果

fill(value).

备注

fill 的一个过时且已弃用的拼写。请改用 fill


专用算法

template<typename T, std::size_t N>
  void swap(array<T, N>& x, array<T, N>& y);
效果

x.swap(y).


比较

template<typename T, std::size_t N>
  constexpr bool operator==(const array<T, N>& x, const array<T, N>& y);
返回

std::equal(x.begin(), x.end(), y.begin()).


template<typename T, std::size_t N>
  constexpr bool operator!=(const array<T, N>& x, const array<T, N>& y);
返回

!(x == y).


template<typename T, std::size_t N>
  constexpr bool operator<(const array<T, N>& x, const array<T, N>& y);
返回

std::lexicographical_compare(x.begin(), x.end(), y.begin(), y.end()).


template<typename T, std::size_t N>
  constexpr bool operator>(const array<T, N>& x, const array<T, N>& y);
返回

y < x.


template<typename T, std::size_t N>
  constexpr bool operator<=(const array<T, N>& x, const array<T, N>& y);
返回

!(y < x).


template<typename T, std::size_t N>
  constexpr bool operator>=(const array<T, N>& x, const array<T, N>& y);
返回

!(x < y).


template<typename T, std::size_t N>
  constexpr auto operator<=>(const array<T, N>& x, const array<T, N>& y)
  -> decltype(x[0] <=> y[0]);
效果

对于 [0..N) 中的每个 i,如果 (x[i] <=> y[i]) != 0,则返回 x[i] <=> y[i]。否则,返回 std::strong_ordering::equal,转换为返回类型。

备注

N 为 0 时,返回类型为 std::strong_ordering,返回值为 std::strong_ordering::equal


特化

template<std::size_t Idx, typename T, std::size_t N>
  constexpr T& get(array<T, N>& arr) noexcept;
强制要求

Idx < N.

返回

arr[Idx].


template<std::size_t Idx, typename T, std::size_t N>
  constexpr const T& get(const array<T, N>& arr) noexcept;
强制要求

Idx < N.

返回

arr[Idx].


创建

template<class T, std::size_t N>
  constexpr array<T, N> to_array( T const (&a)[N] );
返回

一个 array<T, N> r,使得对于 [0..N) 中的每个 ir[i]a[i] 复制而来。

template<class T, std::size_t N>
  constexpr array<T, N> to_array( T (&&a)[N] );
返回

一个 array<T, N> r,使得对于 [0..N) 中的每个 ir[i]std::move(a[i]) 移动而来。

template<class T, std::size_t N>
  constexpr array<T, N> to_array( T const (&&a)[N] );
返回

一个 array<T, N> r,使得对于 [0..N) 中的每个 ir[i]a[i] 复制而来。


设计原理

关于构造函数,存在一个重要的设计权衡:我们可以将 array 实现为“聚合”(参见 C++ 标准第 8.5.1 节,[dcl.init.aggr])。这意味着

  • 数组可以使用花括号括起来的、逗号分隔的初始化列表进行初始化,该列表用于容器元素的初始化,并按递增的下标顺序书写

    boost::array<int,4> a = { { 1, 2, 3 } };

    请注意,如果初始化列表中的元素较少,则每个剩余元素都将进行默认初始化(因此,它具有确定的值)。

然而,这种方法有其缺点:不传递初始化列表意味着元素具有不确定的初始值,因为规则规定聚合可能具有

  • 没有用户声明的构造函数。

  • 没有私有或受保护的非静态数据成员。

  • 没有基类。

  • 没有虚函数。

然而,当前的实现使用了这种方法。

请注意,对于符合标准的编译器,可以使用更少的大括号(根据 C++ 标准的 8.5.1 (11))。也就是说,您可以按如下方式初始化数组

boost::array<int,4> a = { 1, 2, 3 };

更多信息…​

要查找有关在 C++ 中使用普通数组和 STL 框架的更多详细信息,请参阅例如

C++ 标准库——教程与参考
Nicolai M. Josuttis 著
Addison Wesley Longman,1999
ISBN 0-201-37926-0

版权所有 © 2001-2004 Nicolai M. Josuttis

版权所有 © 2012 Marshall Clow