It seems to me that the best solution is avoid at all the double operator[]
and define an at()
function that receive two indexes.
Anyway, if you really (really!) want a double operator[]
solution, the first one has to return an object with requested data and support the second operator[]
I propose the following skeletal example, where a arr2d
(with compile time known dimension) is based over a mono-dimensional std::array
.
#include <array>
#include <iostream>
template <typename T, std::size_t Dim1, std::size_t Dim2>
class Arr2d
{
private:
using int_arr_t = std::array<T, Dim1 * Dim2>;
int_arr_t arr{};
public:
struct foo
{
int_arr_t & arr;
std::size_t const i1;
T & operator[] (std::size_t i2)
{ return arr[i1*Dim1 + i2]; }
T const & operator[] (std::size_t i2) const
{ return arr[i1*Dim1 + i2]; }
};
foo operator[] (std::size_t i1)
{ return {arr, i1}; }
foo const operator[] (std::size_t i1) const
{ return {arr, i1}; }
};
int main ()
{
Arr2d<int, 2, 3> a2d;
a2d[1][2] = 3;
std::cout << a2d[1][2] << std::endl;
}
As you can see, the arr2d::operator[]
return a foo
object containing a reference to the std::array
and the first index.
The foo::operator[]
complete the job, returning a reference (or a constant reference, according the case) to the right element inside the original std::array
.
But, I repepeat: i prefer a couple of at()
functions in Arr2d
T & at (std::size_t i1, std::size_t i2)
{ return arr[i1*Dim1 + i2]; }
T const & at (std::size_t i1, std::size_t i2) const
{ return arr[i1*Dim1 + i2]; }