0

been stuck at this for a while. I have a mathlibrary with a 3x3 matrix class. It used to be dynamic , using a pointer and allocating memory of creation. But as its always gonna be 3x3 I decided to change it, but now I cant use [][] to get values of my array. I am using a proxy class!

class mat3 {
    private:
        double arr[3][3];

    public:
        mat3();
        mat3(double, double, double, double, double,
            double, double, double, double);

                    //Proxy class
        class Proxy {
            private:
                double arr[3];
            public:
                Proxy(const double _arr[3]) { arr = _arr; }
                double& operator[] (const int index) {
                    return arr[index];
                }
                const double& operator[] (const int index) const{
                    return arr[index];
                }
        };

        const Proxy operator[] (const int index) const{
            return Proxy(arr[index]);
        }

        Proxy operator[] (const int index) {
            return Proxy(arr[index]);
        }

Now where arr = _arr i get a compiler error: Error: Expression must be a modifiable Ivalue

What am I doing wrong? How am I suposed to achieve this?

Patrik Nyman
  • 73
  • 2
  • 11
  • You cannot pass arrays by value or assign arrays. – Kerrek SB Nov 26 '14 at 14:20
  • 6
    Why do you insist on the square brackets? Can't you define a custom `operator()(size_t i, size_t j)` that produces the (i, j)th element? – Kerrek SB Nov 26 '14 at 14:21
  • I would totally second Kerrek SB's comment - as formally there is no such thing as `operator[][]`, why not use the function call operator? As the modelled object apparently is a matrix, the function call operator totally makes sense here. – Codor Nov 26 '14 at 14:24
  • To use arrays like that you need to use `std::array` class. But anyway, your proxy should not copy the original array, but contain a point to it. – Neil Kirk Nov 26 '14 at 14:30
  • See https://stackoverflow.com/questions/1386075/overloading-operator-for-a-sparse-vector?rq=1 – sashoalm Nov 26 '14 at 14:34
  • Because I'ave already written a scene graph program where I am using my matrix class and that proxy class worked. Decided to clean up my library, but I'ave decided to go with the function call operator and correct my scene graph program! – Patrik Nyman Nov 26 '14 at 15:02

3 Answers3

1

When you pass an array as a parameter, it gets converted to a pointer, so your constructor is the same as Proxy(const double *_arr) { arr = _arr; } and that's illegal.

Besides, you want to return a reference to the original values in mat3. So change Proxy to use a pointer to double instead:

class Proxy {
private:
   double *arr;
...
};
Dave
  • 331
  • 1
  • 4
1

You don't need Proxy class, you may just do:

class mat3
{
    using row_type = double [3];
public:
    mat3();
    mat3(double, double, double, double, double, double, double, double, double);

    const row_type& operator[](const int index) const { return arr[index]; }
    row_type& operator[](const int index) { return arr[index]; }

private:
    row_type arr[3]; // or double arr[3][3];
};

Note also that using std::array<std::array<double, 3>, 3> arr; would be more intuitive to edit code that C-array.

If really you want to have your Proxy class, you may use:

class mat3
{
    using row_type = double[3];

public:
    mat3();
    mat3(double, double, double, double, double, double, double, double, double);

    class Proxy
    {
    private:
        row_type& arr; // or double (&arr)[3];

    public:
        explicit Proxy(row_type& arr) : arr(arr) {}
        double& operator[](const int index) { return arr[index]; }
        const double& operator[](const int index) const { return arr[index]; }
    };

    const row_type& operator[](const int index) const { return arr[index]; }

    row_type& operator[](const int index) { return arr[index]; }

private:
    row_type arr[3]; // or double arr[3][3];
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
1

Surprisingly this works (I wasn't expecting it to):

#include <iostream>

struct matrix
{
    typedef double ((&reference)[3])[3]; // define a reference type to a 3x3 array

    double array[3][3];

    operator reference() // implicit conversion to 3x3 array reference
    {
        return array;
    }

    void dump()
    {
        for(unsigned x = 0; x < 3; ++x)
            for(unsigned y = 0; y < 3; ++y)
                std::cout << array[x][y] << '\n';
    }
};

int main()
{
    matrix m;

    for(unsigned x = 0; x < 3; ++x)
        for(unsigned y = 0; y < 3; ++y)
            m[x][y] = x * y; // seems to work okay!!!

    m.dump();
}
Galik
  • 47,303
  • 4
  • 80
  • 117