I\'m trying to write a dynamic array template in c++
I\'m currently overloading the [] operators and I\'d like to implement a different behavior based on which side
You cannot overload only on return type.
The standard way to provide constant and non-constant accessor overloads is to differentiate by the constness of this
:
T & get() { return x; }
const T & get() const { return x; } // or T get() const;
For the constant version, you can return either a const-reference or by value, depending on what T
is - const-reference is probably more universally useful.
(In place of get()
you would write operator[](std::size_t i)
, of course. I just wanted to keep it short.)
I don't think this achieves 100% what you had in mind, but that's because you have an error in your reasoning: int b = foo()
will never be a reference to anything, even if foo()
returns a (const or non-const) reference, because b
is declared to be of type int
, not int&
. Practically, you would actually call the non-const version when you say int b = (*temp)[0];
but that isn't actually a problem. (To get the constant version, you'd have to say int b = static_cast<const dynamic_array<int> &>(*temp)[0];
or (*static_cast<const dynamic_array<int> *>(temp))[0]
- but why bother.)
Scott Meyers talked about this in one of the Effective C++ books. Basically the trick was to return a temporary const- or non-const proxy object from the index operators (operator[]()
and operator[]() const
), then overload the assignment and implicit conversion operators for that proxy class. Something like this:
template <class T>
class Array
{
public:
struct proxy {
T& element;
proxy(T& el) : element(el) {}
operator const T& () const {
return element; // For use on RHS of assignment
}
proxy& operator=(const T& rhs) {
// For use on LHS of assignment
// Add your logic here
}
};
const proxy operator[](int i) const {
return proxy(a[i]);
}
proxy operator[](int i) {
return proxy(a[i]);
}
private:
T* a;
};
I may have some of the details wrong but the idea is to defer the decision of what side of the assignment the element is on until an actual attempt is made to assign to it. That is, you don't know what will be done at the time of the operator[] call, but you certainly do when you attempt to assign to the subsequent element reference.