クラス valarray には、operator[](size_t) の定数バージョンと非定数バージョンがあります。定数バージョンは表示されるインデックスの値を返し、非定数バージョンは値の参照を返します。
たとえば、22.2 節の例の続きは次のようになります。
v1[2] = 5; // 非定数インデックス演算子を使用して // 位置 2 の要素を変更する
通常のインデックス演算子のほかに、valarray は、4 つの異なる部分集合演算を提供します。この演算のそれぞれに定数バージョンと 非定数バージョンがあります。定数バージョンは、常に部分集合演算に特有のデータで初期化された新規の valarray を返します。非定数バージョンは、元の valarray のデータを直接参照する補助配列クラスを返します。したがって、各非定数バージョンによって、そこから特定の要素にアクセスできる元の配列へのビューが提供されます。演算子から取得できるのは、これらのいずれかの補助クラスのインスタンスに過ぎないことに注意してください。公開コンストラクタがないため、プログラムはこれらのクラスを直接インスタンス化することはできません。
4 つの部分集合演算は、slice 演算、gslice 演算、mask 演算、indirect 演算です。slice と gslice はどちらも特殊補助クラスを使用して、演算の特性を指定します。これらのクラスはそれぞれ、slice および gslice と呼ばれます。
slice 演算は、Basic Linear Algreba Subprograms (BLAS) に定義された同等の演算のように valarray へのビューを提供します。slice は、開始インデックス、長さ、刻み幅によって定義されます。プログラムは、3 つのパラメータ slice::slice(size_t start, size_t length, size_t stride) を取るコンストラクタを使用して初期化された slice オブジェクトを渡して、slice インデックス演算子を呼び出します。返される配列は、開始インデックスの要素から始まり、事前に選択された各要素の後の刻み幅ステップだけ続く長さの要素のみで構成されます。このプロセスの例を次に示します。
using std::slice; int a[9] = {1,2,3,4,5,6,7,8,9}; valarray<int> all(a,9); //all = {1,2,3,4,5,6,7,8,9} valarray<int> odd = all[slice(0,5,2)]; //odd = {1,3,5,7,9}
この例では、インデックス演算が実際に slice_array を返します。クラス valarray には、このクラスとその他の部分集合演算によって返される補助クラスの変換コンストラクタが含まれます。ただし、奇数は完全に新しい配列なので、参照の意味は失われることに注意してください。クラス slice_array とその他の補助クラスは、ビューの選択とそのビューに基づく新規 valarray の作成の支援のためにのみ存在します。
gslice 演算は、1 対の刻み幅と関連する長さを定義するところが slice と異なります。この 1 対の長さと刻み幅によって、プログラムは 1 次元の valarray を多次元配列として扱い、その配列から多次元スライスを取り出すことができます。 gslice 部分集合演算子は、slice 演算が slice を使用して slice_array を返すのと同様に、gslice 引数を使用して、gslice_array を返すことに注意してください。
以下に、gslice を使用して 3 次元の配列を表す簡単な例を挙げます。この例では、まず最初の 3 つの数値が 2 次元配列の最上行を形成します。この配列の中間行と最下行は、次の 6 つの数値で完成されます。次の 9 つの数値は第 2 の、または中間 2 次元配列を表し、最後の 9 つの数値は後部 2 次元配列を表します。これらは全体で 3 次元立方体を形成します。追加の gslice を使用して、この最初のスライスによって定義された 3 次元立体の複数の軸に沿って slice を引き出す、この例の拡張バージョンについては、『標準 C++ クラスライブラリ・リファレンス』を参照してください。
using std::gslice; int a[27] = {0,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8,9,2,3,4,5,6,7,8,9,10}; size_t lengths[2] = {3,3}; size_t strides[2] = {3,1}; valarray<int> v(a,27); // 初期 valarray valarray<size_t> len(lengths,2); // 長さの valarray valarray<size_t> stride(strides,2); // 刻み幅の valarray valarray<int> v2(0,9); // 汎用スライスを格納するための // valarray v2 = (v[gslice(0,len,stride)]); // 先頭からのスライス = // {0,1,2,3,4,5,6,7,8} v2 = (v[gslice(9,len,stride)]); // 中間からのスライス = // {1,2,3,4,5,6,7,8,9} 後部 2 次元配列 = 2 3 4 5 6 7 8 9 10 中間 2 次元配列 = 1 2 3 4 5 6 7 8 9 前部 2 次元配列 = 0 1 2 3 4 5 6 7 8
第 3 の演算はブール型 mask です。これは、ブール型 valarray の対応する要素が true に設定されているかどうかに基づいて、特定の valarray の要素を選択します。ブール型 valarray のサイズは、インデックス付き valarray のサイズに等しくなければなりません。slice の例と同様、次のコード部分も all 内のすべての奇数を選択します。実際にはこの演算で、mask_array が返されることに注意してください。
int a[9] = {1,2,3,4,5,6,7,8,9}; valarray<int> all(a,9); //all = {1,2,3,4,5,6,7,8,9} bool b[9]= {true,false,true,false,true,false,true,false,true}; valarray<bool> vb(b,9); valarray<int> odd2 = all[vb]; //odd2 = {1,3,5,7,9}
最後に indirect 演算が、size_t の valarray に特定のインデックスが存在するかどうかに基づいて、valarray の要素を選択します。たとえば、valarray<size_t>() をインデックス引数として使用する場合、0 要素を選択して、0 要素の valarray または (インデックス付き配列が const の場合) indirect_array を返します。これに対して、valarray<size_t>(3,1) を使用する場合、第 3 の要素のみを選択するので、 1 要素の valarray または間接配列を返します。以下の例は、やはり all からすべての奇数値要素を選択します。
int a[9] = {1,2,3,4,5,6,7,8,9}; valarray<int> all(a,9); // all = {1,2,3,4,5,6,7,8,9} size_t c[5] = {0,2,4,6,8}; valarray<size_t> in(c,5); valarray<int> oddity = all[in]; // oddity = {1,3,5,7}
各補助配列クラス slice_array、gslice_array、mask_array、indirect_array には、適用されると、元の非定数配列の選択された要素に影響を与える、算術または論理計算代入演算子が含まれます。それぞれ、この演算子は引数として valarray を使用します。valarray 自体には各補助クラスの変換コンストラクタが含まれるため、これらの算術および論理演算子を valarray オブジェクトと補助クラスの間で、また補助クラス間で自由に適用することができます。ただし、補助クラスから valarray への変換では、参照の意味は失われることに注意してください。valarray は、参照・カウントの最適化にもかかわらず、別の valarray のデータは参照しません。
クラス valarray は 4 つの単項演算子、operator+、operator-、operator~、operator! を提供します。演算子が定義されていない型には、これらの演算子を使用することはできません。各演算子は、元の各要素に演算が適用された結果として新規の valarray を返します。たとえば、以下のコードは valarray 内のすべての値を否定します。
float a[4] = {1.0, -2.3, -4.5, 9.0}; valarray<float> v(a,4); valarray<float> neg = -v; // neg = {-1.0, 2.3, 4.5, -9.0}