Как использовать оператор + и оператор = вместе?

У меня небольшая проблема с 2 операторами в моем классе.

Мой класс объявлен:

template <class keyType, class valueType>
class MyMap{

keyType keys[MAX];
valueType values[MAX];
int size;
}

Мне нужно переопределить оператор [], например, когда я звоню: std::cout<<MyMap1["a"];,

keyType& operator[] (keyType key){}

Работает нормально. Я тоже использовал его для выполнения заданий, и это было хорошо, например: MyMap1["a"]="a1";

Код был идеальным. Но по моему operator[] Я увеличиваю size параметр, и это полезно только тогда, когда я хочу сделать назначение. Я не хочу увеличивать его, когда я делаю только std::cout,

Так что, возможно, я должен переопределить operator= функция, но когда я не могу написать:

void operator=(valueType value){}

Потому что левый член MyMap1["a"] = "a1" это keyType и не MyMap тип.

Как я могу сделать ?

0

Решение

Проблема сама по себе не выводится; это то, что вы делаете, когда
Ключа нет Я думаю, что очень важно, чтобы вы указали
прежде чем идти дальше. Есть много возможностей:

  • Вы можете сделать что std::map делает, и вставьте его по умолчанию
    значение. Это очень удобно во многих случаях, но это значит
    что вы не можете использовать [] на постоянной карте.

  • Вы можете сделать так, чтобы оператор возвращал указатель с нулевым значением
    указатель, если объекта нет. Лично мне не нравится
    это для operator[]; это означает, что вы должны писать вещи
    лайк: ValueType* p = myMap[ key ]; if ( p != NULL ) ..., который
    не кажется естественным для [], (С другой стороны, это работает
    хорошо с find или же get функция).

  • Вы можете выбросить исключение (или даже использовать assert, если вы
    обеспечить contains функция, и иметь его в качестве предварительного условия
    []).

  • Вы можете вернуть предопределенное значение по умолчанию. Это своего рода
    противоположность первого решения; это означает, что operator[]
    никогда не будет менять карту, и что нет необходимости
    неконстантная версия.

  • Наконец (и это, кажется, к чему вы стремитесь): вы
    могу иметь operator[] вернуть прокси, чтобы выделиться
    между myMap["a"] используется в качестве значения, и myMap["a"] = something, Я чувствую, что это решение не выходит замуж
    хорошо с тем, как работает C ++, но он используется в других языках
    (например, как Python).

Для последнего решения вы бы использовали что-то вроде:

class MyMap
{
class Proxy
{
MyMap* myOwner;
KeyType myKey;
public:
Proxy( MyMap* owner, KeyType key )
: myOwner( owner )
, myKey( key )
{
}

Proxy const& operator=( ValueType value ) const
{
myOwner->insertOrUpdate( myKey, value );
return *this;
}

operator ValueType() const
{
if ( !myOwner->contains( myKey ) ) {
throw UnknownKeyException( myKey );
}
return myOwner->get( myKey );
}
};

public:
Proxy operator[]( KeyType key )
{
return Proxy( this, key );
}
};
2

Другие решения

Если вы хотите различить операции чтения и записи, решение состоит в том, чтобы вернуть прокси-объект из operator [],

Для примера см. https://stackoverflow.com/a/16132858/320726

1

Msgstr «Но в моем операторе [] я увеличиваю параметр размера».

Не. Проверьте, существует ли ключ, и увеличьте size только если новый ключ вставлен. Когда вы делаете std::coutпредположительно вы делаете это только на существующих парах ключ / значение.

[редактировать] Учитывая комментарий, вот альтернативное решение. В operator[], вернуть MyMap<KeyType, ValueType>::proxy, Это оборачивает MyMap& а также Key, перегрузка MyMap::proxy::operator=(ValueType) назначить новое значение и увеличить size, перегрузка MyMap::proxy::operator ValueType() const чтобы получить значение. Вернуть ValueType() если ключа нету.

1

Когда вы пишете:

auto blah = map[key];

оператор [] вызывается с keyи возвращает значение.

Когда вы пишете:

map[key] = blah;

тогда оператор [ключ] вызывается с key, и он возвращает значение, а затем оператор = вызывается на значение с blah аргумент.

Это означает, что может быть трудно обнаружить, где вы на самом деле читаете или пишете на карту.

Однако, как правило, в случае чтения, случай может вернуться к value const& operator[] const звонил, а во время записи было бы value& operator[] без конст маркеры. Поэтому вы может быть попробуйте перегрузить оператор с помощью константного спецификатора: предоставьте 2 оператора [], один константный, один неконстантный, и увеличьте размер только в последнем.

Это простой легкий но не всегда будет работать правильно, как это может случиться в какой-то момент, чтобы случайно вызвать «operator [] as read», но без ограничения const, определяемого в этой точке компилятором. В настоящее время я не могу точно сказать, когда и как, и если это вообще возможно, но я полагаю, что вы можете ударить это довольно легко, если вы не очень осторожны с константностью.

Если вы нажмете это, то единственная известная мне опция — предоставить обертку для возвращаемого значения в неконстантном режиме и оставить нормальный для константного режима:

myMap::valueType const & operator[](key...) const
mymap::wrapper<myMap::valueType>& operator[](key...)

ваша обертка будет помнить ссылку& к вашей карте и запомните KEY, и эта обертка обеспечит неявное преобразование-TO-valueType, а также предоставит оператор присваивания FROM-valueType-TO-wrappertype. Неявный woudl-тип-преобразования-в-значение выполняет чтение из карты-из-под-данного ключа и не увеличивает счетчик, а оператор = (из-значения-в-тип-оболочки) выполняет запись в карту.

Это бы наверняка сработало, но такой подход может быть устаревшим. Я не бегу с изменениями c’11, так что, возможно, теперь есть более приятный вариант — например, переезд && семантика может что-то изменить здесь, то есть может быть перегрузка

 valueType&& operator[](key)

тоже возможно —- но Я понятия не имею. Я знаю только подход «возврат прозрачной обертки».

РЕДАКТИРОВАТЬ: вот хороший (кажется полный) пример правильной перегрузки оператора [], которая поддерживает чтение и запись, и которая различает эти два:

стек: Как сделать некоторые вещи со значениями, назначенными в операторе индекса?

1

Вы увеличиваете свой size только когда key нет в keys, право? Это то что std::map делает. Так что, если вы просто печатаете содержимое карты, вы будете читать значения для существующих ключей, поэтому size не будет увеличен

0
По вопросам рекламы [email protected]