我面临着编写自己的关联数组并为其重载索引运算符 [] 的任务。我写的,重载看起来像这样:
template<class Key, class Data>
Data& AssociativeArray<Key, Data>::operator[](const Key& key)
{
for (Pair& p : array)
{
if (p.key == key)
{
return p.value;
}
}
// Если ключ не найден создаём новую пару
Pair newPair = { key, Data{} };
array.push_back(newPair);
return array.back().value;
}
//для константного массива
template<class Key, class Data>
const Data& AssociativeArray<Key, Data>::operator[](const Key& key) const
{
for (const Pair& p : array)
{
if (p.key == key)
{
return p.value;
}
}
return Data{};
}
我认为我的问题已经很明显了:在我的实现中,我寻找一个键,如果它不存在,我用这样的键创建一个新的空元素。一方面,这很方便 - 这样我可以分配一个新值,就像常规数组一样:
Arr["newKey"] = "new value";
但另一方面,当尝试从不存在的键中获取值时
std::string str = Arr["newKey"];
它创建一个新的空的,虽然它不应该,但应该抛出一个错误。
所以问题是:我怎样才能正确地做到这一点,以便它在接收值时抛出错误,并在添加它时创建一个元素?
以防万一,这是整个类结构:
template<class Key, class Data>
class AssociativeArray
{
public:
Data& operator[](const Key& key);
const Data& operator[](const Key& key) const;
template<class K, class D>
friend std::ostream& operator<<(std::ostream& os, const AssociativeArray<K, D>& arr);
private:
struct Pair
{
Key key;
Data value;
};
std::vector<Pair> array;
};
template<class Key, class Data>
Data& AssociativeArray<Key, Data>::operator[](const Key& key)
{
for (Pair& p : array)
{
if (p.key == key)
{
return p.value;
}
}
// Если ключ не найден создаём новую пару
Pair newPair = { key, Data{} };
array.push_back(newPair);
return array.back().value;
}
template<class Key, class Data>
const Data& AssociativeArray<Key, Data>::operator[](const Key& key) const
{
for (const Pair& p : array)
{
if (p.key == key)
{
return p.value;
}
}
return Data{};
}
template<class Key, class Data>
std::ostream& operator<<(std::ostream& os, const AssociativeArray<Key, Data>& arr)
{
for (const auto& pair : arr.array)
{
os << "Key: " << pair.key << ", Value: " << pair.value << std::endl;
}
return os;
}
正常情况下这是不可能做到的。最接近的是
[]按值返回辅助对象,并带有重载operator=和operator T。但是转换运算符不允许您像这样编写,例如:foo[42].bar()- 因此您必须添加一个函数来显式读取元素,本着foo[42].get().bar(). 但看起来不太好看。与其试图将两种不同的行为塞进一个
[],不如只制作两个单独的函数/语句。Например, оставить
[]для чтения (и кидать исключение если элемента нет), а для вставки - отдельную функцию.关联数组.hpp
主程序
结论: