moose
moose

Reputation: 11

overload operator[] on return type

There is something that is troubling my brain since a moment: I am trying to overload the [] operator based on the return type. Here is what I need to do:

class A {

private:
    double* data_;
    int N_;
public:
    A (N=0):N_(N){
        data_ = new double[N];
    }
    ~A {delete[] data_;}

    double operator[] (const int i) {
        return data_[i];
    }

    double* operator[] (const int i) {
        return &data[i]; // for example; in fact here i need to return some block of data_ 
    }
};

This code won't compile; and that is my problem. Can someone help me to solve this problem?

PS: I know how to overload normal functions on the return type for example:

int foo ();
string foo ();

I used some tricks that I read in this forum. In this way:

struct func {
    operator string() { return "1";}
    operator int() { return 2; }
};

int main( ) {
    int x    = func(); // calls int version
    string y = func(); // calls string version
    double d = func(); // calls int version
    cout << func() << endl; // calls int version
    func(); // calls neither
}

Thank you.

Upvotes: 1

Views: 1289

Answers (3)

Luc Touraille
Luc Touraille

Reputation: 82041

You can use the same "trick" that you use for functions, that is use a proxy object with conversion operators:

class A
{
  private:
    double* data_;
    int N_;
  public:
    A (int N = 0)
      : N_(N), data_(new double[N])
    {}
    ~A() { delete[] data_; }

    struct proxy
    {
        int i;
        double * data;
        operator double() const
        {
            return data[i];
        }

        operator double*()
        {
            return &data[i];
        }

        operator double const *() const
        {
            return &data[i];
        }
    };

    proxy operator[] (int const i) {
        proxy p { i, data_ };        
        return p;
    }

    proxy const operator[] (int const i) const {
        proxy p { i, data_ };        
        return p;
    }
};

int main()
{
  {
    A a(12);

    double d = a[0];
    double * pd = a[0];
  }

  {
    A const ca(12);

    double d = ca[0];
    //double * pd = ca[0]; // does not compile thanks to overloads on const
    double const * pcd = ca[0];
  }
}

However, I would argue that this is a terrible idea. Having your operator[] return either a value or a pointer to this value is guaranteed to confuse the users of your class, in addition to making it impractical to use in expressions where both types are possible. For instance, std::cout << a[0]; would not compile (ambiguous overloads).

Upvotes: 4

Marek R
Marek R

Reputation: 37597

Probably you need something like that:

class A {

private:
    double* data_;
    int N_;
    ... // other stuff
public:
    double operator[] (const int i) const { // note const here
        return data_[i];
    }

    double& operator[] (const int i) { // note reference here
        return data_[i];
    }
};

also operator should be public to have a sense.

Upvotes: 0

user703016
user703016

Reputation: 37945

Two method overloads must have different signatures. The return type is not part of the signature of a method.

Upvotes: 14

Related Questions