通常、複数の引数の場合operator()
、 ではなくを使用しますoperator[]
。
うーん、それが明らかでない場合operator[][]
、C++ にはありません。operator[]
2回適用しただけです。つまり、その表記法が必要な場合は、最初の表記法が 2 番目の表記法を適用できる結果 (インデックス可能なものまたはプロキシ) を返すようにする必要があります。
以下のコードは、いくつかのアプローチをスケッチしています。好きなものを選択してください。
#include <iostream>
#include <vector>
template< int n >
int& dummy() { static int elem = n; return elem; }
struct Mat1
{
int operator() ( int const x, int const y ) const
{ return dummy<1>(); }
int& operator() ( int const x, int const y )
{ return dummy<1>(); }
Mat1( int, int ) {}
};
struct Mat2
{
int at( int const x, int const y ) const
{ return dummy<2>(); }
int& at( int const x, int const y )
{ return dummy<2>(); }
Mat2( int, int ) {}
};
struct Mat3
{
struct At { At( int x, int y ) {} };
int operator[]( At const i ) const
{ return dummy<3>(); }
int& operator[]( At const i )
{ return dummy<3>(); }
Mat3( int, int ) {}
};
class Mat4
{
protected:
int get( int const x, int const y ) const
{ return dummy<4>(); }
void set( int const x, int const y, int const v ) {}
class AssignmentProxy
{
private:
Mat4* pMat_;
int x_;
int y_;
public:
void operator=( int const v ) const
{ pMat_->set( x_, y_, v ); }
int value() const { return pMat_->get( x_, y_ ); }
operator int () const { return value(); }
AssignmentProxy( Mat4& mat, int const x, int const y )
: pMat_( &mat ), x_( x ), y_( y )
{}
};
public:
int operator()( int const x, int const y ) const
{ return get( x, y ); }
AssignmentProxy operator()( int const x, int const y )
{ return AssignmentProxy( *this, x, y ); }
Mat4( int, int ) {}
};
class Mat5
{
protected:
int at( int const x, int const y ) const
{ return dummy<4>(); }
int& at( int const x, int const y )
{ return dummy<5>(); }
class RowReadAccess
{
private:
Mat5 const* pMat_;
int y_;
public:
int operator[]( int const x ) const
{
return pMat_->at( x, y_ );
}
RowReadAccess( Mat5 const& m, int const y )
: pMat_( &m ), y_( y )
{}
};
class RowRWAccess
{
private:
Mat5* pMat_;
int y_;
public:
int operator[]( int const x ) const
{
return pMat_->at( x, y_ );
}
int& operator[]( int const x )
{
return pMat_->at( x, y_ );
}
RowRWAccess( Mat5& m, int const y )
: pMat_( &m ), y_( y )
{}
};
public:
RowReadAccess operator[]( int const y ) const
{ return RowReadAccess( *this, y ); }
RowRWAccess operator[]( int const y )
{ return RowRWAccess( *this, y ); }
Mat5( int, int ) {}
};
struct Mat6
{
private:
std::vector<int> elems_;
int width_;
int height_;
int indexFor( int const x, int const y ) const
{
return y*width_ + x;
}
public:
int const* operator[]( int const y ) const
{
return &elems_[indexFor( 0, y )];
}
int* operator[]( int const y )
{
return &elems_[indexFor( 0, y )];
}
Mat6( int const w, int const h )
: elems_( w*h, 6 ), width_( w ), height_( h )
{}
};
int main()
{
using namespace std;
enum{ w = 1024, h = 1024 };
typedef Mat3::At At;
Mat1 m1( w, h );
Mat2 m2( w, h );
Mat3 m3( w, h );
Mat4 m4( w, h );
Mat5 m5( w, h );
Mat6 m6( w, h );
wcout
<< m1( 100, 200 ) // No fuss simple, but exposes element ref.
<< m2.at( 100, 200 ) // For those who don't like operators.
<< m3[At( 100, 200)] // If you really want square brackets mnemonic.
<< m4( 100, 200 ) // Hides element ref by using assignment proxy.
<< m5[200][100] // Ditto but with square brackets (more complex).
<< m6[200][100] // The minimum fuss square brackets, exposes elem ref.
<< endl;
}
コードを投稿した後、 の内部ストレージを完全に非表示にしていないことがわかりました。Mat5
のように追加のプロキシ レベルが必要Mat4
です。そのため、そのアプローチは非常に複雑です。私はそれをしません (Mat1
簡単で良いと思います) が、一部の人々はプロキシがクールであり、データを隠すことはさらにクールだと考えています…
要約すると、オーバーロードする「その」正しい方法はありませんoperator[]
。多くの方法があり (上記のコードで示されているように)、それぞれにいくつかのトレードオフがあります。また、一般的には、 を使用する方が適切です。それとoperator()
は対照的に、operator[]
任意の数の引数を取ることができるからです。