web-dev-qa-db-ja.com

複数の引数を持つC ++ []配列演算子?

C++で、複数の引数を取る配列演算子を定義できますか?私はこのようにしてみました:

const T& operator[](const int i, const int j, const int k) const{ 
    return m_cells[k*m_resSqr+j*m_res+i];
}

T& operator[](const int i, const int j, const int k){ 
    return m_cells[k*m_resSqr+j*m_res+i];       
}

しかし、私はこのエラーを得ています:

error C2804 binary operator '[' has too many parameters
49
genesys

いいえ、_operator[]_をオーバーロードして複数の引数を受け入れることはできません。代わりに、operator()をオーバーロードできます。 C++ FAQの Matrixクラスの添え字演算子を作成するにはどうすればよいですか? を参照してください。

44
jamesdlin

_[]_演算子を多重定義して複数の引数を受け入れることはできませんが、代わりにプロキシパターンを使用することもできます。

言い換えると、_a[x][y]_、最初の式(_a[x]_)は、別の_operator[]_を持つ、プロキシタイプという名前の異なるタイプを返します。元のクラスの_storedReferenceToOriginalObject->At(x,y)のようなものを呼び出します。

_a[x,y]_を実行することはできませんが、とにかく通常のC++スタイルの2D配列構文をオーバーロードしたいと思います。

40

C++ 11で利用できる統一された初期化構文を使ってできる素敵な小さなトリックがあります。インデックスを直接取得する代わりに、PODを取得します。

struct indices
{
  std::size_t i, j, k;
};

T& operator[](indices idx)
{
  return m_cells[idx.k * m_resSqr + idx.j * m_res + idx.i];
}

次に、新しい構文を使用します。

my_array<int> arr;
// ...
arr[{1, 2, 3}] = 42;
36

完全を期すために、複数の引数でブラケット演算子を実際に使用する方法があります。それらが基本的なデータ型でない場合、つまり、ブラケット演算子ではなくコンマ演算子をオーバーロードするの場合は、次の投稿を参照してください。カンマのオーバーロード:

https://stackoverflow.com/a/18136340/5836981

免責事項:私の意見では、カンマ演算子のオーバーロードはエラーが発生しやすく、コードがより不明瞭になり、よりエキゾチックなケースでのみ検討する価値があります。いくつかのコードでこのインスタンスを見つけたため、この回答を追加しました。キーが[]演算子(複数の引数でオーバーロードすることはできません)ではなく、演算子であることを理解するのにしばらく時間がかかりました。

10
tePer

C++の任意のタイプとサイズのN次元配列:

この回答は、Pavel Radzivilovskyの回答に触発されたものです。再帰的なテンプレートを初めて試したため、実装の実現に少し苦労しました。他の人が私よりもすぐに理解できるように、私が行ったことを共有したいと思います。

任意の型とサイズのn次元配列を作成するためのc ++テンプレートクラスを作成しました。配列タイプと次元数でインスタンス化する必要があります。サイズは動的に変更できます。 operator [](eg array [の連続的な適用を通じて要素にアクセスできる多次元配列を作成する方法の裸の(ストリップされた)作業バージョンを以下に示しましたx] [y] [z])。このバージョンは、n> 1の次元の配列のみを処理できます。メイン関数は、例として整数の4次元配列を作成する方法を示します。

[〜#〜] edit [〜#〜]:以下の例は、読みやすくするためにminimalであることを覚えておいてください。配列もアクセスの境界チェックも行いません。これを追加するのは簡単で、プログラマに任されています。

#include <stdio.h>
#include <stdlib.h>

template <typename T, int N>
struct array {
    array<T,N>() : data(NULL), offset((int*) malloc(sizeof(int)*N)){}
    array<T,N>(T *data, int *offset) : data(data), offset(offset){}
    array<T,N-1> operator[](int i){return array<T,N-1>(&data[i*offset[N]], offset);}
    bool resize(int *size){
        offset[N-1] = 1;
        int total_size = size[N-1];
        for(int i = N-2; i >= 0; i--){
            total_size *= size[i];
            offset[i] = offset[i+1]*size[i+1];
        }
        return (data = (T*) realloc (data, total_size*sizeof(T)));
    }
    T *data;
    int *offset;
};

template <typename T>
struct array<T,1>{
    array<T,1>(T *data, int *offset) : data(data){}
    T& operator[](int i){return data[i];}
    T *data;
};

int main () {
    array<int, 4> a;

    // create array with dimensions [1][3][3][7]
    int size[4] = { 1, 3, 3, 7 };
    a.resize(size);               

    a[0][1][2][3] = 123;

    return 0;
}

楽しい。

2
gospes