目錄
Boost.MultiArray 由多個組件組成。MultiArray 概念定義了多維容器的一個泛型接口。multi_array 是一個參照 MultiArray 的通用容器類。multi_array_ref 和 const_multi_array_ref 則是適配器類。通過使用它們,你可以像操作一個
multi_array 一樣操作任意的連續數據塊。const_multi_array_ref 與
multi_array_ref 的區別在於其元素不可以通過接口來修改。最後還有幾個輔助類用於創建和特化數組,還有一些全局對像被定義為本庫接口的一部分。
要使用 Boost.MultiArray, 你必須在你的源程序中包含頭文件
boost/multi_array.hpp. 該文件將以下聲明帶入到當前域:
namespace boost {
namespace multi_array_types {
typedef *unspecified* index;
typedef *unspecified* size_type;
typedef *unspecified* difference_type;
typedef *unspecified* index_range;
typedef *unspecified* extent_range;
typedef *unspecified* index_gen;
typedef *unspecified* extent_gen;
}
template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class multi_array;
template <typename ValueType,
std::size_t NumDims>
class multi_array_ref;
template <typename ValueType,
std::size_t NumDims>
class const_multi_array_ref;
multi_array_types::extent_gen extents;
multi_array_types::index_gen indices;
template <typename Array, int N> class subarray_gen;
template <typename Array, int N> class const_subarray_gen;
template <typename Array, int N> class array_view_gen;
template <typename Array, int N> class const_array_view_gen;
class c_storage_order;
class fortran_storage_order;
template <std::size_t NumDims> class general_storage_order;
}
MultiArray 概念定義了一個分層嵌套容器的接口。它指定了訪問元素、遍歷容器和創建數據視圖等操作。MultiArray 定義了一個靈活的內存模式以適應不同的數據佈局。
在一個 MultiArray 容器層次的每一層(或每一維)都可視為一組有序的容器,其中每一個都包含相同數量和類型的值。容器層次的深度就是 MultiArray 的 維度。MultiArray 是遞歸定義的;每一層的容器都符合 MultiArray。一個 MultiArray 的每個維度都有各自的大小,由所有維度的大小所組成的列表定義了整個 MultiArray 的 形狀。該容器層次的基礎可以視為1維的 MultiArrays. 它們的值是所有被容器包含的元素,而不是其中一部分。它們就是 MultiArray 的元素。
與其它容器概念一樣,MultiArray 提供了迭代器來遍歷它的值。另外,也可以用方括號來直接訪問這些值。
MultiArray 還提供了創建特定視圖的方法。視圖 可以讓你將一個 MultiArray 中的元素的子集視為一個獨立的
MultiArray. 由於視圖是引向同一組底層元素的,所以對視圖的元素進行修改地反映到原來的
MultiArray 中。例如,給定一組3維"立體"的元素,它的一個2維切片可以被視為一個無關的
MultiArray.
視圖可以用 index_gen 和
index_range 對像來創建。index_range 代表了某個維度被包含在視圖中的元素範圍。index_gen 則將這些範圍數據集合起來,並進行簿記工作,以確定返回的視圖類型。MultiArray 的 operator[]
必須被傳入對
index_gen::operator[] 的 N 次鏈式調用的結果,即:
indices[a0][a1]...[aN];
其中 N 為
MultiArray 的維度,而
indices 是一個類型為 index_gen 的對象。視圖的類型取決於 index_gen 所指定的退化的維度數量。一個退化的維度表示對某個維度向
index_gen 指定單個值。例如,如果
indices 是一個類型為
index_gen 的對象,那麼以下例子:
indices[index_range(0,5)][2][index_range(0,4)];
其中第二個維度是退化的。由以上語句生成的視圖具有2個維度,形狀為 5 x 4.
如果上面的 "2" 被替換為另一個 index_range 對象,例如:
indices[index_range(0,5)][index_range(0,2)][index_range(0,4)];
那麼該視圖有3個維度。
MultiArray 還提供了關於所含元素的內存佈局的信息。它存儲元素的內存模式由4個屬性來定義:原點、形狀、索引基數和步幅。原點是以 a[0][0]...[0]來訪問的元素在內存中的地址,其中
a 為一個 MultiArray.
形狀是一個數字列表,指定容器的各個維度的大小。例如,列表中第一個數字是最外層容器的大小,第二個數字是下一層容器的大小,依此類推。索引基數是一個有
符號整數的列表,指定了容器中第一個值的索引。在同一個維度的所有容器共享一個相同的索引基數。注意,由於索引基數可以為正,所以原點不一定位於
MultiArray
的元素的內存中。步幅決定了索引值如何映射到內存的偏移量。它們適應多種可能的元素佈局。例如,一個2維數組的元素可以按行存儲(即每一行的元素被連續存
儲)或者按列存儲(即每一列的元素被連續存儲)。
以下是將用於 MultiArray 接口說明的符號描述。
表 1. 符號
A |
一個參照 MultiArray 的類型 |
a,b |
類型 A 的對象 |
NumDims |
A 的維度數 |
Dims |
某個滿足
0<Dims<NumDims 的數字,用作維度參數
|
indices |
一個由對 index_gen::operator[](index_range) 的多次鏈式調用所創建的對象 |
index_list |
一個對象,其類型參照了 Collection |
idx |
一個有符號整數值 |
tmp |
類型
boost::array<index,NumDims> 的對象 |
表 2. 相關類型
| 類型 | 說明 |
|---|---|
value_type |
容器的值類型。如果 NumDims == 1, 則它就是
element. 否則,它是最直接的嵌套容器的值類型。
|
reference
|
所含值的引用類型。如果 NumDims == 1, 則它就是
element&. 否則,它與
template subarray<NumDims-1>::type 類型相同。
|
const_reference
|
所含值的常量引用類型。如果 NumDims == 1, 則它就是
const element&. 否則,它與
template const_subarray<NumDims-1>::type 類型相同。
|
size_type
|
這是一個無符號整數類型。主要用於指定數組的形狀。 |
difference_type
|
這是一個有符號整數類型,用於表示兩個迭代器間的距離。它與
std::iterator_traits<iterator>::difference_type 類型相同。
|
iterator |
A 的迭代器。如果 NumDims == 1, 則它符合
隨機訪問迭代器。否則,它符合
隨機訪問遍歷迭代器,可讀迭代器 和
可寫迭代器。
|
const_iterator
|
A 的常量迭代器。
|
reverse_iterator
|
反向迭代器,用於對 A 進行反向迭代。
|
const_reverse_iterator
|
A 的反向常量迭代器。
|
element
|
存儲在 MultiArray 的基礎層的對象的類型。類型與
template subarray<1>::value_type 相同
|
index
|
這是一個有符號整數類型,用於 A 中的索引。也被用於表示步幅和索引基數。
|
index_gen
|
該類型用於創建一個 index_range 的 tuple,傳遞給 operator[],以創建一個 array_view<Dims>::type 對象。
|
index_range
|
該類型指定一個
MultiArray 的某些維度的索引範圍。該範圍對於一個 array_view<Dims>::type 對象是可見的。
|
template subarray<Dims>::type
|
這是 Dims 維度的子數組類型。它是 A 的 (NumDims - Dims)
維度的引用類型,同樣符合
MultiArray.
|
template const_subarray<Dims>::type
|
這是常量的子數組類型。 |
template array_view<Dims>::type
|
這是 Dims 維度的視圖類型。通過調用 operator[]( 返回。它符合 MultiArray.
|
template
const_array_view<Dims>::type
|
這是 Dims 維度的常量視圖類型。
|
表 3. 有效表達式
| 表達式 | 返回類型 | 語義 |
|---|---|---|
a.shape() |
const size_type* |
返回由 NumDims 個元素組成的列表,表示每個維度的長度。
|
a.strides() |
const index* |
返回由 NumDims 個元素組成的列表,表示與每個維度相關的步幅。在訪問數組中的值時,步幅用於計算一個元素在內存中的位置。
|
a.index_bases() |
const index* |
返回由 NumDims 個元素組成的列表,表示每個維度第一個元素的索引。
|
a.origin() |
element* 如果 a 是可變的,否則為
const element*
|
返回由表達式
a[0][0]...[0]所訪問的元素的地址。如果有某個索引基數是正的,該元素將不存在,但該地址還是可以用來定位一個給定索引的有效元素。
|
a.num_dimensions() |
size_type |
返回數組的維數(注意 a.num_dimensions() == NumDims)。 |
a.num_elements() |
size_type |
返回數組中包含的元素數量。等價於以下代碼:
std::accumulate(a.shape(),a.shape+a.num_dimensions(), |
a.size() |
size_type |
返回
a 中包含的值的數量。等價於 a.shape()[0];
|
a(index_list) |
element& 如果 a 是可變的,否則為
const element&
|
該表達式訪問 a 的某個特定元素。index_list 是表示所返回的元素的唯一索引組合。它等價於以下代碼(忽略其中的臨時對像):
// 用步幅與索引相乘 |
a.begin() |
iterator 如果 a 是可變的,否則為
const_iterator
|
返回指向
a 的始端的迭代器。 |
a.end() |
iterator 如果 a 是可變的,否則為
const_iterator
|
返回指向 a 的末端的迭代器。 |
a.rbegin() |
reverse_iterator 如果 a 是可變的,否則為
const_reverse_iterator
|
返回一個反向迭代器,指向反向 a 的始端。
|
a.rend() |
reverse_iterator 如果 a 是可變的,否則為
const_reverse_iterator
|
返回一個反向迭代器,指向反向 a 的末端。
|
a[idx] |
reference 如果 a 是可變的,否則為
const_reference
|
返回一個引用類型,綁定到 a 中索引為
idx 的值。注意,如果
i 為該維度的索引基數,以上表達式將返回第 (idx-i)個元素(從零起計)。該表達式等價於
*(a.begin()+idx-a.index_bases()[0]);.
|
a[indices] |
array_view<Dims>::type 如果 a 是可變的,否則為
const_array_view<Dims>::type
|
該表達式生成一個數組的視圖,依據構成 indices 的
index_range 和 index 值。
|
a == b |
bool | 執行對 a 和 b 中各個值的逐一比較。元素類型必須是 相等性可比較的,該表達式才有效。 |
a < b |
bool | 執行對 a 和 b 中各個值的逐一比較。元素類型必須是 小於關係可比較的,該表達式才有效。 |
a <= b |
bool | 執行對 a 和 b 中各個值的逐一比較。元素類型必須是 相等性可比較的 且
小於關係可比較的,該表達式才有效。 |
a > b |
bool | 執行對 a 和 b 中各個值的逐一比較。元素類型必須是 相等性可比較的 且
小於關係可比較的,該表達式才有效。 |
a >= b |
bool | 執行對 a 和 b 中各個值的逐一比較。元素類型必須是 小於關係可比較的,該表達式才有效。 |
表 4. 不變式
| 有效範圍 | [a.begin(),a.end()) 為有效範圍。
|
| 範圍大小 |
a.size() == std::distance(a.begin(),a.end());.
|
| 完整性 |
對區間
[a.begin(),a.end()) 進行迭代,將遍歷 a 中的每一個 value_type.
|
| 等價的訪問方法 | 調用 a[a1][a2]...[aN],其中 N==NumDims,產生的結果與調用
a(index_list),其中 index_list
是由值 a1...aN 組成的 Collection 是相同的。
|
以下 MultiArray 相關類型定義了創建已有 MultiArray 的視圖的接口。以下描述其接口及規則。
index_range 對像表示一個指定步幅的半開區間。它們可以被聚集起來(用一個
index_gen 對像)傳遞給某個 MultiArray 的 operator[]
以創建一個數組視圖。在創建視圖時,每個 index_range 代表 MultiArray 的某個維度上的有效索引範圍。通過這些範圍組合可以訪問到的元素構成了這個視圖。在某些情況下,可以創建一個沒有指定開始和結束值的
index_range. 這樣,該對象就被解釋為從 MultiArray 的某個維度的始端開始,在該維度的末端結束。
index_range 對像有多種方式進行構造和修改,為索引範圍提供方便且清晰的表達方式。為了指定區間,index_range 提供了一組構造函數,可變成員函數,以及一種新穎的不等式操作符。使用這種不等式操作符,可以這樣來表示非開區間 [5,10):
5 <= index_range() < 10;
或
4 < index_range() <= 9;
等等。以下描述
index_range 的接口。
表 7. 有效表達式
| 表達式 | 返回類型 | 語義 |
|---|---|---|
index_range(idx1,idx2,idx3) |
index_range |
構造一個 index_range,表示步幅為 idx3 的區間 [idx1,idx2) |
index_range(idx1,idx2) |
index_range |
構造一個 index_range,表示單位步幅的區間 [idx1,idx2). 等價於
index_range(idx1,idx2,1). |
index_range() |
index_range |
構造一個 index_range,不指定開始值和結束值。 |
i.start(idx1) |
index& |
將 i 的開始索引設為
idx. |
i.finish(idx) |
index& |
將 i 的結束索引設為
idx. |
i.stride(idx) |
index& |
將 i 的步幅設為
idx. |
i.start() |
index |
返回 i 的開始索引。 |
i.finish() |
index |
返回 i 的結束索引。 |
i.stride() |
index |
返回 i 的步幅。 |
i.get_start(idx) |
index |
如果 i 指定了開始值,則等價於 i.start(). 否則返回 idx. |
i.get_finish(idx) |
index |
如果 i 指定了結束值,則等價於 i.finish(). 否則返回 idx. |
i.size(idx) |
size_type |
如果 i 指定了開始值和結束值,則等價於 (i.finish()-i.start())/i.stride(). 否則返回 idx. |
i < idx |
index |
指定結束值的另一種語法。表示有效索引的區間不包含
idx. 等價於
index_range(r.start(), idx, r.stride()) |
i <= idx |
index |
指定結束值的另一種語法。表示有效索引的區間包含
idx. 等價於
index_range(r.start(), idx + 1, r.stride()) |
idx < i |
index |
指定開始值的另一種語法。表示有效索引的區間不包含
idx. 等價於
index_range(idx + 1, i.finish(), i.stride()). |
idx <= i |
index |
指定開始值的另一種語法。表示有效索引的區間包含
idx. 等價於
index_range(idx, i.finish(), i.stride()). |
i + idx |
index |
該表達式將 i 的開始值和結束值都增加 idx. 等價於
index_range(r.start()+idx, r.finish()+idx, r.stride()) |
i - idx |
index |
該表達式將 i 的開始值和結束值都減少 idx. 等價於
index_range(r.start()-idx, r.finish()-idx, r.stride()) |
index_gen 將
index_range 對像聚集起來用作指定視圖的參數。通過對 operator[] 的鏈式調用,保存相關的區間和維度信息,用於在 MultiArray 中初始化一個新的視圖。
表 8. 符號
Dims,Ranges |
無符號整數值。 |
x |
類型
template gen_type<Dims,Ranges>::type 的對象 |
i |
類型 index_range 的對象。 |
idx |
類型 index 的對象 |
表 9. 相關類型
| 類型 | 說明 |
|---|---|
index |
有符號整數類型。用於指定退化的維度。 |
size_type |
無符號整數類型。用於報告 index_range
所表示的範圍大小。 |
template gen_type::<Dims,Ranges>::type |
該類型生成器命名了對
index_gen::operator[]
進行 Dims 次鏈式調用的結果。
Ranges 參數由退化的區間(即調用
operator[](index))的數量所決定。注意,index_gen 和
gen_type<0,0>::type 是相同的類型。 |
表 10. 有效表達式
| 表達式 | 返回類型 | 語義 |
|---|---|---|
index_gen() |
gen_type<0,0>::type |
構造一個 index_gen
對象。該對象可用於生成 多個 index_range 值所組成的 tuple. |
x[i] |
gen_type<Dims+1,Ranges+1>::type
|
返回一個新對象,包含所有以前的
index_range 對像再外加
i. 對
operator[] 的鏈式調用就是聚集
index_range 對象的方法。 |
x[idx] |
gen_type<Dims,Ranges>::type
|
返回一個新對象,包含所有以前的
index_range 對像再外加一個退化區間 index_range(idx,idx). 注意,這並不等價於 x[index_range(idx,idx)],後者的返回類型為
gen_type<Dims+1,Ranges+1>::type.
|
Boost.MultiArray 定義了一個數組類
multi_array, 以及兩個適配器類
multi_array_ref 和
const_multi_array_ref. 這三個類均符合
MultiArray 概念,所以它們共享了多項功能。multi_array_ref 與
multi_array 的區別在於,multi_array 管理它所擁有的內存,而
multi_array_ref 則被傳入一塊內存且該塊內存是由外部管理的。const_multi_array_ref 與
multi_array_ref 的區別在於它所適配的底層元素不可以通過其接口進行修改,雖然某些數組屬性,包括數組的形狀和索引基數,可以被修改。這些類所具備的共有功能說明如下。
註:前提條件、作用和實現。在以下幾節中,我們會用一些C++代碼片斷來說明象前提條件、作用和後續條件等約束。沒有必要對數組組件 的底層實現進行描述;這些代碼描述了所需的輸入以及特定操作的行為。不滿足前提條件將導致未定義的行為。不是所有列出的作用(如複製構造函數等)都必須精 確模仿。這些代碼片斷的主要意圖是捉住所描述的操作的本質。
查詢
element* data();
const element* data() const;
返回一個指針,指向數組的數據所在的連續內存塊的開頭。如果所有數組的所有維度都是從零起計的,且均按升序存儲,則它等價於 origin(). 注意,const_multi_array_ref 只提供該函數的 const 版本。
element* origin();
const element* origin() const;
返回
multi_array 的原點元素。注意,const_multi_array_ref 只提供該函數的 const
版本。(MultiArray 所必需的)
const index* index_bases();返回
multi_array 的索引基數。(MultiArray 所必需的)
const index* strides();返回
multi_array 的步幅。(MultiArray 所必需的)
const size_type* shape();返回 multi_array 的形狀。(MultiArray 所必需的)
比較操作
bool operator==(const *array-type*& rhs);
bool operator!=(const *array-type*& rhs);
bool operator<(const *array-type*& rhs);
bool operator>(const *array-type*& rhs);
bool operator>=(const *array-type*& rhs);
bool operator<=(const *array-type*& rhs);
每個比較操作按兩個數組的值類型進行比較。(MultiArray 所必需的)
前提條件:element 必須支持在
multi_array 上調用的相應比較操作。
複雜度:O(num_elements()).
修改操作
template <typename SizeList>
void reshape(const SizeList& sizes)
該操作修改 multi_array 的形狀。元素數量及索引基數保持不變,但嵌套容器層次中各層的值數量可能被改變。
SizeList 的要求:SizeList 必須符合
Collection.
前提條件:
std::accumulate(sizes.begin(),sizes.end(),size_type(1),std::times<size_type>()) == this->num_elements();
sizes.size() == NumDims;
後續條件:std::equal(sizes.begin(),sizes.end(),this->shape) == true;
template <typename BaseList>
void reindex(const BaseList& values);
該操作根據 values 的值修改 multi_array 的索引基數。
BaseList 的要求:BaseList 必須符合 Collection.
前提條件:values.size() == NumDims;
後續條件:std::equal(values.begin(),values.end(),this->index_bases());
void reindex(index value);
該操作將
multi_array所有維度的索引基數改為value.
後續條件:
std::count_if(this->index_bases(),this->index_bases()+this->num_dimensions(),
std::bind_2nd(std::equal_to<index>(),value)) ==
this->num_dimensions();
multi_array 是一個支持隨機訪問迭代的多維容器。它的維數在編譯期是固定的,但它的形狀和所包含的元素數量可以在構造時指定。元素的數量在
multi_array 的生命週期內是固定的,但容器的形狀可以改變。multi_array 用一個可替換的分配器(allocator)來管理其數據元素。
符合的概念:MultiArray, 可複製構造。根據其元素類型,也可能符合 相等性可比較 和 小於關係可比較。
摘要:
namespace boost {
template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class multi_array {
public:
// types:
typedef ValueType element;
typedef *unspecified* value_type;
typedef *unspecified* reference;
typedef *unspecified* const_reference;
typedef *unspecified* difference_type;
typedef *unspecified* iterator;
typedef *unspecified* const_iterator;
typedef *unspecified* reverse_iterator;
typedef *unspecified* const_reverse_iterator;
typedef multi_array_types::size_type size_type;
typedef multi_array_types::index index;
typedef multi_array_types::index_gen index_gen;
typedef multi_array_types::index_range index_range;
typedef multi_array_types::extent_gen extent_gen;
typedef multi_array_types::extent_range extent_range;
typedef *unspecified* storage_order_type;
// template typedefs
template <std::size_t Dims> struct subarray;
template <std::size_t Dims> struct const_subarray;
template <std::size_t Dims> struct array_view;
template <std::size_t Dims> struct const_array_view;
// constructors and destructors
multi_array();
template <typename ExtentList>
explicit multi_array(const ExtentList& sizes,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());
explicit multi_array(const extents_tuple& ranges,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());
multi_array(const multi_array& x);
multi_array(const const_multi_array_ref<ValueType,NumDims>& x);
multi_array(const const_subarray<NumDims>::type& x);
multi_array(const const_array_view<NumDims>::type& x);
multi_array(const multi_array_ref<ValueType,NumDims>& x);
multi_array(const subarray<NumDims>::type& x);
multi_array(const array_view<NumDims>::type& x);
~multi_array();
// modifiers
multi_array& operator=(const multi_array& x);
template <class Array> multi_array& operator=(const Array& x);
// iterators:
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
// capacity:
size_type size() const;
size_type num_elements() const;
size_type num_dimensions() const;
// element access:
template <typename IndexList>
element& operator()(const IndexList& indices);
template <typename IndexList>
const element& operator()(const IndexList& indices) const;
reference operator[](index i);
const_reference operator[](index i) const;
array_view<Dims>::type operator[](const indices_tuple& r);
const_array_view<Dims>::type operator[](const indices_tuple& r) const;
// queries
element* data();
const element* data() const;
element* origin();
const element* origin() const;
const size_type* shape() const;
const index* strides() const;
const index* index_bases() const;
const storage_order_type& storage_order() const;
// comparators
bool operator==(const multi_array& rhs);
bool operator!=(const multi_array& rhs);
bool operator<(const multi_array& rhs);
bool operator>(const multi_array& rhs);
bool operator>=(const multi_array& rhs);
bool operator<=(const multi_array& rhs);
// modifiers:
template <typename InputIterator>
void assign(InputIterator begin, InputIterator end);
template <typename SizeList>
void reshape(const SizeList& sizes)
template <typename BaseList> void reindex(const BaseList& values);
void reindex(index value);
template <typename ExtentList>
multi_array& resize(const ExtentList& extents);
multi_array& resize(extents_tuple& extents);
};
構造函數
template <typename ExtentList>
explicit multi_array(const ExtentList& sizes,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());
用給定參數構造一個 multi_array. sizes 指定了被構造 multi_array 的形狀。store
指定了存儲的順序或各維度的內存佈局。alloc 用於分配被包含的元素。
ExtentList 的要求:ExtentList 必須符合 Collection.
前提條件:sizes.size() == NumDims;
explicit multi_array(extent_gen::gen_type<NumDims>::type ranges,
const storage_order_type& store = c_storage_order(),
const Allocator& alloc = Allocator());
用給定參數構造一個 multi_array. ranges 指定了被構造 multi_array 的形狀和索引基數。它是對
extent_gen::operator[] 進行
NumDims 次鏈式調用所得到的結果。store
指定了存儲的順序或各維度的內存佈局。alloc 用於分配存儲在 multi_array
中的元素的內存。
multi_array(const multi_array& x);
multi_array(const const_multi_array_ref<ValueType,NumDims>& x);
multi_array(const const_subarray<NumDims>::type& x);
multi_array(const const_array_view<NumDims>::type& x);
multi_array(const multi_array_ref<ValueType,NumDims>& x);
multi_array(const subarray<NumDims>::type& x);
multi_array(const array_view<NumDims>::type& x);
這些構造函數都是用於構造一個 multi_array 並執行一次對 x 的深拷貝。
複雜度:執行 O(x.num_elements()) 次
element 的複製構造函數。
multi_array();
構造一個 multi_array,其形狀為 (0,...,0),不包含任何元素。
關於構造函數的補充說明:multi_array 構造表達式
multi_array<int,3> A(boost::extents[5][4][3]);
和
boost::array<multi_array_base::index,3> my_extents = {{5, 4, 3}};
multi_array<int,3> A(my_extents);
是等價的。
修改操作
multi_array& operator=(const multi_array& x);
template <class Array> multi_array& operator=(const Array& x);
將 x
的各個元素的複製到當前的 multi_array.
Array 的要求:Array 必須符合 MultiArray.
前提條件:
std::equal(this->shape(),this->shape()+this->num_dimensions(),
x.shape());
後續條件:
(*.this) == x;
複雜度:賦值操作執行
O(x.num_elements()) 次 element 的複製構造函數。
template <typename InputIterator>
void assign(InputIterator begin, InputIterator end);
將區間
[begin,end) 中的元素複製到數組中。等價於
std::copy(begin,end,this->data()).
前提條件:std::distance(begin,end) == this->num_elements();
複雜度:assign 成員函數執行
O(this->num_elements()) 次
ValueType 的複製構造函數。
multi_array& resize(extent_gen::gen_type<NumDims>::type extents);
template <typename ExtentList>
multi_array& resize(const ExtentList& extents);
該函數將數組的大小修改為由
extents 指定的形狀,extents 可以是生成的長度列表或符合 Collection 概念。數組中的內容盡可能保持不變;如果新的數組大小變小了,則會丟失部分數據。因數組大小改變而新創建的元素均由
element 的缺省構造函數進行初始化。
查詢
storage_order_type& storage_order() const;
該查詢返回與
multi_array 相關聯的存儲順序對象。它可以用於構造另一個具有相同存儲順序的新數組。
multi_array_ref 是一個多維容器適配器。它為任意存儲了某種元素的連續內存塊提供 MultiArray 的接口。multi_array_ref 給出了與 multi_array 相同的接口,除了構造函數以外。
符合的概念:multi_array_ref 符合
MultiArray,
可複製構造,並且依據其元素類型,還可能符合
相等性可比較 和 小於關係可比較。這裡只對在 multi_array 中沒有的操作給出詳細說明。
摘要
namespace boost {
template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class multi_array_ref {
public:
// types:
typedef ValueType element;
typedef *unspecified* value_type;
typedef *unspecified* reference;
typedef *unspecified* const_reference;
typedef *unspecified* difference_type;
typedef *unspecified* iterator;
typedef *unspecified* const_iterator;
typedef *unspecified* reverse_iterator;
typedef *unspecified* const_reverse_iterator;
typedef multi_array_types::size_type size_type;
typedef multi_array_types::index index;
typedef multi_array_types::index_gen index_gen;
typedef multi_array_types::index_range index_range;
typedef multi_array_types::extent_gen extent_gen;
typedef multi_array_types::extent_range extent_range;
typedef *unspecified* storage_order_type;
// template typedefs
template <std::size_t Dims> struct subarray;
template <std::size_t Dims> struct const_subarray;
template <std::size_t Dims> struct array_view;
template <std::size_t Dims> struct const_array_view;
// structors
template <typename ExtentList>
explicit multi_array_ref(element* data, const ExtentList& sizes,
const storage_order_type& store = c_storage_order());
explicit multi_array_ref(element* data, const extents_tuple& ranges,
const storage_order_type& store = c_storage_order());
multi_array_ref(const multi_array_ref& x);
~multi_array_ref();
// modifiers
multi_array_ref& operator=(const multi_array_ref& x);
template <class Array> multi_array_ref& operator=(const Array& x);
// iterators:
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
// capacity:
size_type size() const;
size_type num_elements() const;
size_type num_dimensions() const;
// element access:
template <typename IndexList>
element& operator()(const IndexList& indices);
template <typename IndexList>
const element& operator()(const IndexList& indices) const;
reference operator[](index i);
const_reference operator[](index i) const;
array_view<Dims>::type operator[](const indices_tuple& r);
const_array_view<Dims>::type operator[](const indices_tuple& r) const;
// queries
element* data();
const element* data() const;
element* origin();
const element* origin() const;
const size_type* shape() const;
const index* strides() const;
const index* index_bases() const;
const storage_order_type& storage_order() const;
// comparators
bool operator==(const multi_array_ref& rhs);
bool operator!=(const multi_array_ref& rhs);
bool operator<(const multi_array_ref& rhs);
bool operator>(const multi_array_ref& rhs);
bool operator>=(const multi_array_ref& rhs);
bool operator<=(const multi_array_ref& rhs);
// modifiers:
template <typename InputIterator>
void assign(InputIterator begin, InputIterator end);
template <typename SizeList>
void reshape(const SizeList& sizes)
template <typename BaseList> void reindex(const BaseList& values);
void reindex(index value);
};
構造函數
template <typename ExtentList>
explicit multi_array_ref(element* data,
const ExtentList& sizes,
const storage_order& store = c_storage_order());
以給定參數構造一個 multi_array_ref. sizes 指定了被構造 multi_array_ref 的形狀。store
指定了存儲順序或數組各維度的內存佈局。(譯註:原文中有一個alloc參數,應為筆誤)
ExtentList 的要求:ExtentList 必須符合 Collection.
前提條件:sizes.size() == NumDims;
explicit multi_array_ref(element* data,
extent_gen::gen_type<NumDims>::type ranges,
const storage_order& store = c_storage_order());
以給定參數構造一個 multi_array_ref. ranges 指定了被構造 multi_array_ref 的形狀和索引基數。它是對
extent_gen::operator[] 進行
NumDims 次鏈式調用所得到的結果。store
指定了存儲順序或數組各維度的內存佈局。
multi_array_ref(const multi_array_ref& x);
構造 x 的一個淺拷貝。
複雜度:常量時間(作為對比,將其與 multi_array 類的複製構造函數進行比較)。
修改操作
multi_array_ref& operator=(const multi_array_ref& x);
template <class Array> multi_array_ref& operator=(const Array& x);
將 x
中的元素複製到當前的 multi_array_ref.
Array 的要求:Array 必須符合 MultiArray.
前提條件:
std::equal(this->shape(),this->shape()+this->num_dimensions(),
x.shape());
後續條件:
(*.this) == x;
複雜度:賦值操作執行
O(x.num_elements()) 次 element 的複製構造函數。
const_multi_array_ref 是一個多維容器適配器。它為任意存儲了某種元素的連續內存塊提供 MultiArray 的接口。給出了與 multi_array 相同的接口,除了構造函數以外。
符合的概念:const_multi_array_ref 符合 MultiArray, 可複製構造,並且依據其元素類型,還可能符合 相等性可比較 和 小於關係可比較。這裡只對在 multi_array 中沒有的操作給出詳細說明。
摘要
namespace boost {
template <typename ValueType,
std::size_t NumDims,
typename Allocator = std::allocator<ValueType> >
class const_multi_array_ref {
public:
// types:
typedef ValueType element;
typedef *unspecified* value_type;
typedef *unspecified* reference;
typedef *unspecified* const_reference;
typedef *unspecified* difference_type;
typedef *unspecified* iterator;
typedef *unspecified* const_iterator;
typedef *unspecified* reverse_iterator;
typedef *unspecified* const_reverse_iterator;
typedef multi_array_types::size_type size_type;
typedef multi_array_types::index index;
typedef multi_array_types::index_gen index_gen;
typedef multi_array_types::index_range index_range;
typedef multi_array_types::extent_gen extent_gen;
typedef multi_array_types::extent_range extent_range;
typedef *unspecified* storage_order_type;
// template typedefs
template <std::size_t Dims> struct subarray;
template <std::size_t Dims> struct const_subarray;
template <std::size_t Dims> struct array_view;
template <std::size_t Dims> struct const_array_view;
// structors
template <typename ExtentList>
explicit const_multi_array_ref(const element* data, const ExtentList& sizes,
const storage_order_type& store = c_storage_order());
explicit const_multi_array_ref(const element* data, const extents_tuple& ranges,
const storage_order_type& store = c_storage_order());
const_multi_array_ref(const const_multi_array_ref& x);
~const_multi_array_ref();
// iterators:
const_iterator begin() const;
const_iterator end() const;
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
// capacity:
size_type size() const;
size_type num_elements() const;
size_type num_dimensions() const;
// element access:
template <typename IndexList>
const element& operator()(const IndexList& indices) const;
const_reference operator[](index i) const;
const_array_view<Dims>::type operator[](const indices_tuple& r) const;
// queries
const element* data() const;
const element* origin() const;
const size_type* shape() const;
const index* strides() const;
const index* index_bases() const;
const storage_order_type& storage_order() const;
// comparators
bool operator==(const const_multi_array_ref& rhs);
bool operator!=(const const_multi_array_ref& rhs);
bool operator<(const const_multi_array_ref& rhs);
bool operator>(const const_multi_array_ref& rhs);
bool operator>=(const const_multi_array_ref& rhs);
bool operator<=(const const_multi_array_ref& rhs);
// modifiers:
template <typename SizeList>
void reshape(const SizeList& sizes)
template <typename BaseList> void reindex(const BaseList& values);
void reindex(index value);
};
構造函數
template <typename ExtentList>
explicit const_multi_array_ref(const element* data,
const ExtentList& sizes,
const storage_order& store = c_storage_order());
以給定參數構造一個 const_multi_array_ref. sizes 指定了被構造 const_multi_array_ref 的形狀。store
指定了存儲順序或數組各維度的內存佈局。
ExtentList 的要求:ExtentList 必須符合 Collection.
前提條件:sizes.size() == NumDims;
explicit const_multi_array_ref(const element* data,
extent_gen::gen_type<NumDims>::type ranges,
const storage_order& store = c_storage_order());
作用:以給定參數構造一個 const_multi_array_ref. ranges 指定了被構造 const_multi_array_ref
的形狀和索引基數。它是對 extent_gen::operator[] 進行 NumDims
次鏈式調用所得到的結果。store 指定了存儲順序或數組各維度的內存佈局。
const_multi_array_ref(const const_multi_array_ref& x);
作用:構造 x 的一個淺拷貝。
namespace multi_array_types {
typedef *unspecified* index;
typedef *unspecified* size_type;
typedef *unspecified* difference_type;
typedef *unspecified* index_range;
typedef *unspecified* extent_range;
typedef *unspecified* index_gen;
typedef *unspecified* extent_gen;
}
名字空間 multi_array_types 定義了一些與 multi_array,
multi_array_ref, 和
const_multi_array_ref 相關的類型,這些類型不依賴於模板參數。這些類型被所有 Boost.Multiarray 組件共同使用。它們被定義在一個可以方便訪問的名字空間中。除了 extent_gen 和
extent_range 以外,這些類型遵循 MultiArray 所要求且在其概念定義中被描述的同名規則。extent_gen 和
extent_range 則描述如下。
extent_range 對像定義了一個半開區間。它為
multi_array, multi_array_ref, 和 const_multi_array_ref 的構造函數提供形狀和索引的信息。多個 extent_range 被聚集起來傳遞給數組的構造函數(詳細說明請見
extent_gen)。
摘要
class extent_range {
public:
typedef multi_array_types::index index;
typedef multi_array_types::size_type size_type;
// Structors
extent_range(index start, index finish);
extent_range(index finish);
~extent_range();
// Queries
index start();
index finish();
size_type size();
};
符合的概念:可缺省構造,可複製構造
方法與類型
extent_range(index start, index finish)該構造函數定義一個半開區間
[start,finish). 表達式
finish 必須大於 start.
extent_range(index finish)該構造函數定義一個半開區間
[0,finish). finish
的值必須為正。
index start()該函數返回表示該區間的第一個索引。
index finish()該函數返回半開區間的上界值。注意,該區間不包含該值。
size_type size()該函數返回指定區間的大小。它等價於 finish()-start().
extent_gen 類定義了一個接口,用於聚集數組的形狀和索引信息,以傳遞給 multi_array,
multi_array_ref, 或 const_multi_array_ref 的構造函數。該接口模仿了C++中聲明內建數組類型的語法。例如,在C++中,一個3維 int 數組聲明如下:
int A[3][4][5],
類似的 multi_array 則聲明如下:
multi_array<int,3> A(extents[3][4][5]).
摘要
template <std::size_t NumRanges>
class *implementation_defined* {
public:
typedef multi_array_types::index index;
typedef multi_array_types::size_type size_type;
template <std::size_t NumRanges> class gen_type;
gen_type<NumRanges+1>::type operator[](const range& a_range) const;
gen_type<NumRanges+1>::type operator[](index idx) const;
};
typedef *implementation_defined*<0> extent_gen;
方法與類型
template gen_type::<Ranges>::type該類型生成器用於指定對
extent_gen::operator[] 的
Ranges 次鏈式調用的結果。類型
extent_gen 與
gen_type<0>::type 相同。
gen_type<NumRanges+1>::type
operator[](const extent_range& a_range) const;該函數返回一個新的對象,包含所有以前的
extent_range 對象並加上
a_range. extent_range
對像通過對
operator[] 的鏈式調用來聚集。
gen_type<NumRanges+1>::type
operator[](index idx) const;該函數返回一個新的對象,包含所有以前的 extent_range 對象並加上
extent_range(0,idx). 該函數使得數組構造函數具有與傳統C的多維數組聲明類似的語法。
為了語法上的方便,Boost.MultiArray 定義了兩個全局對像作為其接口的一部分。這些對像扮演了對象生成器的角色;包含它們的表達式可以創建其它所需的對象。
在某些情形下,這兩個全局對象可能被認為開銷太大。可以通過在包含
boost/multi_array.hpp 之前定義預處理符號
BOOST_MULTI_ARRAY_NO_GENERATORS 來禁止它們的構造。
namespace boost {
multi_array_base::extent_gen extents;
}
Boost.MultiArray 的數組類使用
extents 全局對像來在構造時指定數組的形狀。例如,一個 3 乘 3 乘 3 的 multi_array 構造如下:
multi_array<int,3> A(extents[3][3][3]);
同樣的數組也可以通過顯式一個局部的 extent_gen
對像來創建,不過使用全局對象可以不需要進行聲明。
Boost.MultiArray 提供了 traits 類 subarray_gen,
const_subarray_gen,
array_view_gen, 和 const_array_view_gen, 用於在函數模板中表示數組的各個相關類型。通常,沒有比使用嵌套類型生成器更為方便的方法了,不過本庫的作者發現,有些C++編譯器不能正確處理嵌套在函數模板的參數類型中的模板。為此,這些生成器需要另外的解決方法。以下代碼片斷示範了 array_view_gen
traits 類和相關數組的 array_view 類型之間的對應關係:
template <typename Array>
void my_function() {
typedef typename Array::template array_view<3>::type view1_t;
typedef typename boost::array_view_gen<Array,3>::type view2_t;
// ...
}
在上例中,view1_t 和
view2_t 具有相同類型。
多維數組表示了由多個元素容器組成的層次結構,而這些元素必須被置於內存中。所以,一個多維數組可以用多種方法在內存中表示。
例如,有以下矩陣所表示的一個2維數組:

這個數組在C++中可以表示為:
int a[3][4] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
這是一個行優先存儲的例子,每行的元素被連續存儲。除了讓C++來處理對數組元素的訪問以外,你也可以自己手工管理這個數組以及它的索引。其中一種方法可能是這樣:
int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
int s[] = { 4, 1 };
在聲明了 a 和步幅 s 之後,數組的元素 a(i,j)
可以用以下表達式來訪問:
*a+i*s[0]+j*s[1]
.
同一個2維數組也可以按列存儲如下:
int a[] = { 0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11 };
int s[] = { 3, 1 };
注意,這裡的步幅有所不同。所以,前面給出的訪問元素的表達式必須與該數據和步幅一起使用。
除了維度的順序,還有可能以降序方式保存某個維度。例如,回到第一個例子,數組的第一個維度,即行,可能以相反的順序保存如下:
int data[] = { 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3 };
int *a = data + 8;
int s[] = { -4, 1 };
注意,在這個例子中,a 必須顯式地設置為原點。在前面的例子中,保存在內存中的第一個元素即為原點;而這裡不再是如此了。
另外,第二個維度,即列,也可能以相反的順序保存,而行則以升序保存:
int data[] = { 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8 };
int *a = data + 3;
int s[] = { 4, -1 };
最後,也可能兩個維度均以降序保存:
int data[] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
int *a = data + 11;
int s[] = { -4, -1 };
以上各個數組都是等價的。前面給出的訪問 a(i,j) 的表達式在各種內存佈局下均得到相同的值。Boost.MultiArray 數組可以按以上所說的各種定制的存儲參數來創建。因此,已有的數據可以被適配(通過 multi_array_ref 或
const_multi_array_ref)以適應數組的抽像。該特性的一個常見用法是,包裝一個需要與Fortran程序交互的數組,使它可以被C++和Fortran同時操作。下面幾節將講述用於指定內存佈局的 Boost.MultiArray 組件。
class c_storage_order {
c_storage_order();
};
c_storage_order 用於指定一個數組以與原生C++多維數組相同的內存佈局來存儲其元素,即從最後一維到第一維。這是本庫所提供的各種數組的缺省存儲順序。
class fortran_storage_order {
fortran_storage_order();
};
fortran_storage_order 用於指定一個數組以與Fortran多維數組相同的內存佈局來存儲其元素,即從第一維到最後一維。
template <std::size_t NumDims>
class general_storage_order {
template <typename OrderingIter, typename AscendingIter>
general_storage_order(OrderingIter ordering, AscendingIter ascending);
};
general_storage_order 允許用戶為一個數組中的內容指定各種不同的內存佈局。構造出來的對象將被傳遞給數組的構造函數,以指定存儲順序。
OrderingIter 和 AscendingIter
必須符合 InputIterator 概念。這兩個迭代器都必須引向包含 NumDims
個元素的區間。AscendingIter 指向一組可轉換為 bool 的對象。對像值為
true 代表該維以升序存儲,為 false 則代表該維以降序存儲。OrderingIter 則指定保存各個維度的順序。