2016-03-23 4 views
0

多次元括弧をどのようにオーバーロードできますか?多次元括弧のオーバーロード

私は、n - ベクトル空間内のポイントにアクセスできるクラスがあるとします。たとえば:

int main() { 
    NSpaceVector nsv; // Assume initializes all to 0 
    nsv[2][4][7][4][0][7][6] = 2; 
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2 
    cout << nsv[1][4][7][4][0][7][6] << endl; //-> 0 
    return 0; 
} 

私はこれをコンパイルするために取得することはできません。

class NSpaceVector { 
    private: 
     int vectorSpace[8][8][8][8][8][8][8]; 
    public:   
     const NSpaceVector operator[][][][][][][](int i, int j, int k, int l, int m, int n, int p)const {return vectorSpace[i][j][k][l][m][n][p]; } 
     NSpaceVector operator[][][][][][][](int i, int j, int k, int l, int m, int n, int p) {return vectorSpace[i][j][k][l][m][n][p]; } 
} 
unsigned long & operator [](int i) {return registers[i];} 

は、私は何をしたいのは、私がこの場所へのインデックスそうのようにできるように、ブラケット演算子をオーバーロードです。何か案は? Thx、Keith:^)

+3

多次元括弧はC++でそのような演算子がないのでオーバーロードできません。代わりに、一次元ブラケットの各オーバーロードは別のプロキシを返すようなインデックス作成の第2レベルを意味するなど、一種のプロキシオブジェクトを返すために単一のブラケットをオーバーロードする必要があります。 – SergeyA

+0

これを 'operator()'で行うより良い方法を読むためにこれを与えてください:https://isocpp.org/wiki/faq/operator-overloading#matrix-array-of-array – user4581301

+1

あるいは、構文。 'nsv(1,2,3,4,5,6,7)'や 'nsv [{1,2,3,4,5,6,7}]'と同様です。 –

答えて

1

アイデアはありますか?

レベルごとにoperator[]()をオーバーロードし、戻り値のタイプが別のoperator[]()のオーバーロードを持つようにするオプションがあります。


コメント欄で述べたように、このように通常呼operator()をオーバーロードして解決される:

int operator()(size_t dim1, size_t dim2, ... size_t dimn); 
+0

この回答は私を不快にします。これをC++ 17仕様に追加する可能性はありますか? – kmiklas

+0

@kmiklas申し訳ありませんが、事実を伝えることによってあなたに感謝します。いいえ、C++ 17仕様のAFAIKを使った演算子のオーバーロード構文に変更はありません.C++標準委員会がその懸案事項を変更することを納得させることはできません。 –

+0

@kmiklas zilch。あなたがタイムマシンを持っていない限り、それは無限です。 –

1

標準答えが[](左から右へ)それぞれを有することであるがためのプロキシを返します正しいネストされたサブセット。最後のものは実際にデータへの参照を返します。あなたのスキームでは、ネストされた型をテンプレート化して生産を自動化するのが最も簡単です。

神秘user4581301が述べているように、それは

nsv(2,4,7,4,0,7,6) 

を提供するために、はるかに簡単です、ご希望のクラスのサンプルテンプレートの生産は一時的なプロキシオブジェクトを使用するよりも、おそらく簡単です:

template <size_t Width, size_t Depth, typename T=int> 
struct SubSpace; 

template <size_t Width, typename T> 
struct SubSpace<Width,0,T> { 
    std::array<T, Width> array; 

    T& operator[] (size_t i) { return array[i]; } 
    T const& operator[] (size_t i) const { return array[i]; } 
}; 

template <size_t Width, size_t Depth, typename T> 
struct SubSpace { 
    using Nested = SubSpace<Width, Depth-1, T>; 
    std::array<Nested, Width> array; 

    Nested& operator[] (size_t i) { return array[i]; } 
    Nested const& operator[] (size_t i) const { return array[i]; } 
}; 


using NSpaceVector = SubSpace<8,6>; 

int main() 
{ 
    NSpaceVector nsv; 
    nsv[2][4][7][4][0][7][6] = 2; 
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2 
} 

注意これは現在デフォルトでは配列メンバを初期化していませんが、とにかく集約初期化を使用できます:

NSpaceVector nsv {}; // value-initialize every element 
    nsv[2][4][7][4][0][7][6] = 2; 
    cout << nsv[2][4][7][4][0][7][6] << endl; //-> 2 
    cout << nsv[2][4][7][4][0][7][5] << endl; //-> 0 

はまた、深さが0で終了するので、これはトップレベルのラッパーを使用してクリーンアップすることができ、SubSpace<8,6>はあなたが望んでいた8x7の結果を与えることに注意してください、私が代わりにDepth==1に終了すると、誰かがインスタンス化したときにすべてが間違って行く持って消極的です事故によってSubSpace<0,0>が発生します。


シンプルそれでも、あなたはあなたのクラスのいかなる行動をしたいかに応じて、このです:

struct OtherSpaceVector { 
    int s[8][8][8][8][8][8][8]; 

    auto operator[] (size_t i) -> decltype(s[i]) { return s[i]; } 
}; 

int main() 
{ 
    OtherSpaceVector osv{}; 
    osv[2][4][7][4][0][7][6] = 2; 
    std::cout << osv[2][4][7][4][0][7][6] << '\n'; 
    std::cout << osv[2][4][7][4][0][7][5] << '\n'; 
} 

それは寸法を変更することが困難だとテンプレートのバージョンよりも脆い感じているが、それあなたが提供したユースケースでも動作します。