Как и в заголовке, я пытаюсь написать карту классов шаблонов, которая строится на векторе structs, где я держу ключ, который является строкой и значением шаблона TYPE. Существует короткая основная программа, которая представляет использование моего класса:
int main()
{
map<int> iv;
iv["john"] = 23;
int ia = iv["john"]++;
int ib = iv["john"];
cout << ia << " " << ib << endl; // prints 23 24
try{
int ic = iv["jack"]; // should throw an exception
}catch(map<int>::Uninitialized&)
{
cout << "Uninitialized map element!" << endl;
};
}
И есть класс, который мне удалось написать:
class map
{
private:
struct FIELD
{
string key;
TYPE value;
};
vector<FIELD> data;
public:
TYPE& operator[] (const string index)
{
typename vector<FIELD>::iterator idx;
for(idx = data.begin(); idx != data.end(); ++idx)
{
if(idx->key == index) return idx->value;
}
if(idx == data.end())
{
FIELD toAdd;
toAdd.key = index;
data.push_back(toAdd);
}
for(idx = data.begin(); idx != data.end(); ++idx)
{
if(idx->key == index) return idx->value;
}
return idx->value;
}
};
Он работает только для операций присваивания, таких как "iv [" john "] = 23; но когда я пытаюсь читать элементы, которые не инициализируются, оператор [] создает новый элемент, содержащий только ключ, и это неправильно. Я знаю, что нет такой вещи, как проверка того, является ли значение неинициализированным. Проблема в том, что оператор записи и чтения операции [], и я не совсем понимаю, как сделать исключение в этой ситуации. Я посмотрел по всему Интернету и обнаружил, что могу создать два оператора индексирования: один для чтения и один для записи - вот так:
TYPE& operator[] (const string index)
TYPE operator[] (const stirng index) const;
и компилятор будет знать, когда использовать. Но я думаю, это не решит проблему вообще.
Не пытайтесь повторно реализовать std::map
, создайте вместо него псевдоним:
template<class Type>
using map = std::map<std::string, Type>;
Не забудьте импортировать using namespace std;
, так как считается плохой практикой, и в этом случае у вас будет столкновение имен.
И да, std::map::operator[]
всегда создавал элемент внутри карты. Вы можете использовать std::map::at
чтобы заставить его std::out_of_range
исключение std::out_of_range
если элемент там отсутствует, или проверить с помощью map.find(key) == map.end()
.
Ваш главный станет:
int main() {
map<int> iv;
iv["john"] = 23;
int ia = iv["john"]++;
int ib = iv["john"];
std::cout << ia << " " << ib << std::endl; // prints 23 24
try {
int ic = iv.at("jack");
// ^^^^ ^
} catch(const std::out_of_range&) {
// ^^^^^^^^^^^^^^^^^^^^^^^^
std::cout << "Uninitialized map element!" << std::endl;
};
}
std::map
они сделали это там, гдеoperator[]
всегда создает новый элемент автоматически с созданным по умолчаниюT
, иat
это тот, который вызовет исключение, если его там нет.