Любой компилятор C ++ должен работать таким образом. Вы не можете выбрать перегрузку в зависимости от того, будет ли ваша функция отображаться слева или справа от оператора присваивания. Перегрузка выбирается в зависимости от того, является ли экземпляр постоянным или нет.
Свойства в C # и перегрузка на основе константности метода в C ++ просто оказываются разными вещами, которые служат разным целям.
Интересно, связан ли ваш вопрос с Почему у нас не может быть неизменной версии оператора [] для карты ?
Можно эмулировать различие между использованием в левой части присваивания и в других контекстах с прокси-классом (я надеюсь, что этот термин правильный), но это не очень хорошо работает, и я не рекомендую его из-за оператора неявного преобразования (обратите внимание, что для вывода результата требуется явное приведение).
#include <iostream>
#include <map>
#include <string>
#include <stdexcept>
using namespace std;
template <typename KeyType, typename ValueType>
class DictProxy;
template <typename KeyType, typename ValueType>
class ConstDictProxy;
template <typename TKey, typename TValue>
class Dictionary{
public:
map<TKey, TValue> internal;
DictProxy<TKey, TValue> operator[](TKey const & key);
ConstDictProxy<TKey, TValue> operator[](TKey const & key) const;
};
template <typename KeyType, typename ValueType>
class DictProxy
{
std::map<KeyType, ValueType>* p_map;
const KeyType* key;
DictProxy(std::map<KeyType, ValueType>* p_map, const KeyType* key): p_map(p_map), key(key) {}
friend class Dictionary<KeyType, ValueType>;
public:
void operator=(const ValueType& value) const {
cout << "operator[] used on the left side of assignment with key " << *key << endl;
(*p_map)[*key] = value;
}
operator ValueType&() const {
cout << "operator[] used in a different context with " << *key << endl;
//you used at here
//it is in the C++0x standard, but generally not in online references?
typename std::map<KeyType, ValueType>::iterator it = p_map->find(*key);
if (it == p_map->end()) {
throw std::range_error("Missing key in map");
}
return it->second;
}
};
template <typename KeyType, typename ValueType>
class ConstDictProxy
{
const std::map<KeyType, ValueType>* p_map;
const KeyType* key;
ConstDictProxy(const std::map<KeyType, ValueType>* p_map, const KeyType* key): p_map(p_map), key(key) {}
friend class Dictionary<KeyType, ValueType>;
public:
operator const ValueType&() const {
cout << "operator[] const used in a different context with " << *key << endl;
typename std::map<KeyType, ValueType>::const_iterator it = p_map->find(*key);
if (it == p_map->end()) {
throw std::range_error("Missing key in map");
}
return it->second;
}
};
template <typename TKey, typename TValue>
DictProxy<TKey, TValue> Dictionary<TKey, TValue>::operator[](TKey const & key)
{
return DictProxy<TKey, TValue>(&internal, &key);
}
template <typename TKey, typename TValue>
ConstDictProxy<TKey, TValue> Dictionary<TKey, TValue>::operator[](TKey const & key) const
{
return ConstDictProxy<TKey, TValue>(&internal, &key);
}
int main(int argc, char* argv[])
{
Dictionary<string, string> dict;
dict["1"] = "one";
cout << "first one: " << string(dict["1"]) << endl;
const Dictionary<string, string>& r_dict = dict;
cout << "first one: " << string(r_dict["1"]) << endl;
return 0;
}
(Некоторое повторное использование кода должно позволять игнорировать DRY при реализации DictProxy и ConstDictProxy.)
Однако, если ваш вопрос связан с этим, то решение IMO состоит в том, чтобы использовать метод at()
, когда вы не хотите добавлять значения по умолчанию, и operator[]
, если вы это делаете. Я подозреваю, что первый является дополнением к C ++ 0x, хотя?