Возможно ли opIndexAssign в C ++? - PullRequest
4 голосов
/ 09 февраля 2011

Язык программирования D версии 2 имеет изящный метод для перегрузки такого выражения :

classInstance[someName] = someValue;

Или как функция D, определенная в этом небольшом примере :

ref Map opIndexAssign(ref const(ValueT) value, ref const(NameT) name)
{
    this.insert(name, value);
    return this;
}

Возможно ли это в C ++ (в идеале без использования STL)? Если да, то как?

Ответы [ 2 ]

8 голосов
/ 09 февраля 2011

Обычно вы используете прокси-объект в качестве типа возврата operator[]; этот объект будет иметь пользовательский operator= определенный. Специализация vector<bool> в стандартной библиотеке C ++ использует прокси для получения искомого поведения. Однако решение на основе прокси не так прозрачно, как версия D. Код выглядит примерно так:

class proxy;

class my_map {
  public:
  proxy operator[](const key_type& k);
  // Rest of class
};

class proxy {
  my_map& m;
  key_type k;
  friend class my_map;
  proxy(my_map& m, const key_type& k): m(m), k(k) {}

  public:
  operator value_type() const {return m.read(k);}
  proxy& operator=(const value_type& v) {m.write(k, v); return *this;}
};

proxy my_map::operator[](const key_type& k) {
  return proxy(*this, k);
}
3 голосов
/ 09 февраля 2011

Не знаком с D, я должен предположить, что ваш первый фрагмент кода в итоге вызывает opIndexAssign с value = someValue и name = someName?

Если это так, это может быть сделано в C ++, но не таким простым способом. Вы можете перегрузить оператор [] и вернуть прокси-объект с помощью пользовательского оператора = следующим образом (очень простой, надуманный пример):

class MyProxy
{
    public:
        MyProxy (int& ref) : valueRef(ref) { }
        MyProxy& operator = (int value) { valueRef = value; return *this; }
    private:
        int& valueRef;
};

class MyClass
{
    public:
        MyProxy operator [] (std::string name);
    private:
        int myVal;
};

MyProxy& MyClass::operator [] (std::string name)
{
    if (name.compare("myVal"))
        return MyProxy(myVal);

    ...
}

int main ( )
{
    MyClass mc;

    mc["myVal"] = 10; // Sets mc.myVal to 10
}

Я бы хотел подчеркнуть, что вышеприведенный код не очень красивый / правильно сформированный код, это просто иллюстрация. Это не было проверено.

РЕДАКТИРОВАТЬ: Слишком быстро для меня, Иеремия !!!

...