Boost C++ 库

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

Boost.Array - Boost C++ 函数库

简介

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

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

在他的书Generic Programming and the STL中,Matthew H. Austern 为普通静态大小数组介绍了一个有用的包装类,称为 block。它比普通数组更安全,性能也没有变差。在The C++ Programming Language,第三版中,Bjarne Stroustrup 介绍了一个类似的类,称为 c_array,我(Nicolai Josuttis)在他的书The C++ Standard Library - A Tutorial and Reference中稍作修改地介绍,称为 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

参考

Header <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 } };

    请注意,如果初始化列表中的元素少于成员数量,则每个剩余的元素将按默认方式初始化(因此,它具有确定的值)。

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

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

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

  • 没有基类。

  • 没有虚函数。

尽管如此,当前实现采用了这种方法。

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

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

更多信息…​

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

The C++ Standard Library - A Tutorial and Reference
作者:Nicolai M. Josuttis
Addison Wesley Longman, 1999
ISBN 0-201-37926-0

Copyright © 2001-2004 Nicolai M. Josuttis

Copyright © 2012 Marshall Clow