Во втором примере будет вызвана неконстантная версия, потому что преобразование не требуется, и вызов, не требующий преобразования, является лучшим соответствием, чем вызов, требующий преобразования.
В конечном счете, однако, у вас есть основная проблема: то, что вам действительно нужно, - это поведение, которое меняется в зависимости от того, используете ли вы свой объект в качестве значения или значения, а const
на самом деле этого не делает. Чтобы заставить его работать правильно, вы обычно хотите вернуть прокси-объект и перегрузить operator=
и operator T
для прокси-объекта:
template <class T>
class myarray {
T *ptr;
class proxy {
T &val;
proxy &operator=(proxy const &p); // assignment not allowed.
public:
proxy(T &t) : val(t) {}
operator T() const { return val; }
proxy &operator=(T const&t) { val = t; return *this; }
};
proxy const operator[](int sub) const { return proxy(ptr[sub]); }
proxy operator[](int sub) { return proxy(ptr[sub]); }
// obviously other stuff like ctors needed.
};
Теперь мы получаем нормальное поведение - когда / если наш array<int>
(или любой другой тип) является константным, будет использоваться наш operator[] const
, и он даст const proxy
. Поскольку его операторы присваивания не const, попытка их использования не удастся (не скомпилируется).
OTOH, если исходный array<int>
не был константным, мы получим неконстантный прокси-сервер, и в этом случае мы можем использовать как operator T
, так и operator=
, и иметь возможность как читать, так и записывать значение в array<int>
.