Операторы индекса для класса с переменной члена std::map
Я пытаюсь создать класс, который упаковывает std:: map и выполняет проверку, чтобы убедиться, что ключи являются одной из утвержденных допустимых строк, а также инициализирует карту, чтобы иметь значения по умолчанию для всех утвержденных допустимых строк. У меня возникли проблемы с тем, чтобы заставить работать индексный оператор, в частности его константную версию.
Вот мой код прототипирования класса:
#include <set>
#include <string>
#include <map>
class foo {
public:
foo() {}
const double & operator[](const std::string key) const {
return data[key];
}
private:
static const std::set<std::string> validkeys;
std::map<std::string, double> data;
};
const std::set<std::string> foo::validkeys = {"foo1", "foo2"};
Когда я компилирую это (используя g++ с -std= C++0x), я получаю эту ошибку компиляции:
|| /home/luke/tmp/testmap.cc: In member function 'double& foo::operator[](std::string) const':
testmap.cc|10 col 22 error| passing 'const std::map<std::basic_string<char>, double>' as
'this' argument of 'mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const
key_type&) [with _Key = std::basic_string<char>, _Tp = double, _Compare =
std::less<std::basic_string<char> >, _Alloc = std::allocator<std::pair<const
std::basic_string<char>, double> >, mapped_type = double, key_type =
std::basic_string<char>]' discards qualifiers
Ничто из того, что я делаю, не может исправить это. я пытался
- превращение validkeys в std:: set и data std:: map
- используя const char * вместо string
- возвращая const double или double вместо const double &
- используя список и вектор вместо набора для хранения валидных ключей
Я не знаю, правильно ли я подхожу к этой проблеме, так что если есть какой-то другой простой способ создать класс, который обеспечивает такую функциональность:
foo a;
a["foo2"] = a["foo1"] = 5.0;
// This would raise a std::runtime_error because I would be checking that
// "foo3" isn't in validkeys
a["foo3"] = 4.0;
Любые предложения с благодарностью.
РЕШЕНИЕ
Следующее работает точно так, как я хочу, у меня даже есть основное исключение, когда вы пытаетесь установить или получить ключ, которого нет в наборе допустимых ключей:
#include <iostream>
#include <string>
#include <map>
#include <set>
#include <stdexcept>
class myfooexception : public std::runtime_error
{
public:
myfooexception(const std::string & s)
: std::runtime_error(s + " is not a valid key.") {}
};
class foo {
public:
foo() {
for (std::set<std::string>::iterator it = validkeys.begin();
it != validkeys.end();
++it) {
data[*it] = 0.0;
}
}
const double & operator[](const std::string & key) const {
if (data.find(key) == data.end()) {
throw myfooexception(key);
} else {
return data.find(key)->second;
}
}
double & operator[](const std::string & key) {
if (data.find(key) == data.end()) {
throw myfooexception(key);
} else {
return data[key];
}
}
private:
static const std::set<std::string> validkeys;
std::map<std::string, double> data;
};
const std::set<std::string> foo::validkeys = {"foo1", "foo2"};
int main(void)
{
foo a;
a["foo1"] = 2.0;
a["foo1"] = a["foo2"] = 1.5;
// a["foo3"] = 2.3; // raises exception: foo3 is is not a valid key
const foo b;
std::cout << b["foo1"]; // should be ok
// b["foo1"] = 5.0; // compliation error, as expected: b is const.
return 0;
}
4 ответа
operator []
не объявлено const
в std::map
, поскольку operator []
также вставляет новый элемент, когда ключ не найден, и возвращает ссылку на его сопоставленное значение. Вы можете использовать map::find
метод вместо map::operator[]
если ты хочешь operator[]
быть const
,
Индекс оператора для std::map
является неконстантным, поскольку вставляет новый элемент, если он еще не существует. Если вы хотите, чтобы ваша карта имела постоянный operator[]
, вам нужно написать тот, который использует map::find()
и тесты против map::end()
, обрабатывая случай ошибки.
Вы пытаетесь изменить объект const!! пожалуйста, удалите const членов set.const, которые нельзя изменить после инициализации.
Вы пытаетесь присвоить std::map
но ваша функция объявлена const
а также возвращаясь const
, Удалить оба const
и это должно работать.