2

I want to define a class myVector that support both assignment operator= and bracket access e.g myclass(1) = 0.5. See a dummy example below

class myVector
{
public:
    vector<double> _v;
    myVector(unsigned int size) : _v(size, 0) { }

    double& operator()(int i)
    {
        return _v[i];
    }

    unsigned int size() const { return _v.size(); }

    myVector& operator=(const myVector& v)
    {
        _v.resize(v.size());
        for(int i=0;i<v.size();i++)
            _v[i] = v(i);
    }
}

This code cannot be compiled since () is not defined as a constant function. This is because I want to enable direct assignment such as myvector(1) = 2. To solve this problem, I can only think of two solutions. One is to define sth. like double getValue(int i) const but this seems weird since some duplicate code is added. The other is to remove const from the signature of () function, but that is undesirable as well. I am sure there will be a good work around but I cannot find it.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
Peter Trade
  • 21
  • 1
  • 2
  • 1
    Why so complicated - you can just say `_v = v;`, or `_v.swap(v);`. – Kerrek SB Mar 30 '12 at 21:08
  • 5
    those round brackets are called "parentheses", and the operator is called "the function call operator" – Ben Voigt Mar 30 '12 at 21:09
  • This is nearly an exact duplicate of an earlier question. http://stackoverflow.com/questions/5762042/const-overloaded-operator-function-and-its-invocation/5762323. [My answer](http://stackoverflow.com/a/5762323/179910) to that applies here as well. – Jerry Coffin Mar 30 '12 at 21:17

2 Answers2

2

The correct solution is "both". Member functions, including operators, can be overloaded on const-ness (the this pointer is effectively a parameter and takes part in overload resolution).

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

NOTE: With non-member operators, the left-hand object isn't just like a parameter, it IS a parameter.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
0

For the particular case of the operator(), you should just provide two overloads:

double& operator()( int i ) { return _v[i]; }
double operator()( int i ) const { return _v[i]; } // [1]

If this was a templated container, the second overload would return a const&, but given that it is a double, returning a copy is fine.

Now as a recommendation, you can implement the copy constructor, and then implement a simple swap function:

void myVector::swap( myVector & lhs ) {
   _v.swap( lhs._v );
}

With those two tools in place, then you can use the idiomatic implementation of operator=:

myVector& myVector::operator=( myVector rhs ) { // by value
   swap( *this, rhs );
   return *this;
}

The other thing is that it does not make sense to roll your own loop to copy the vectors, they already know how to do that by themselves, so _v = v._v; has the same effect as your loop.

David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489