模板类中使用unordered_multimap的make_pair及迭代器问题
咱们来逐个拆解并解决你遇到的两个问题:
问题1:addElement调用时的类型转换错误
你在实例化MapTemplate<QString>并调用addElement时碰到的“无法将参数从QString转换为_Ty1&&”错误,根源出在std::make_pair的显式模板参数指定上。
当你写std::make_pair<QString, TYPE>(elementName, T)时,强制要求make_pair把第二个参数绑定到TYPE&&(右值引用),但你传入的programName是一个左值(普通QString变量),这就触发了类型不匹配的错误。
解决方法非常直接:
- 不要显式指定
make_pair的模板参数,让编译器自动推导类型即可:void addElement(const QString& elementName, const TYPE& T) { unorderedMultiMap.insert(std::make_pair(elementName, T)); } - 更推荐用
emplace,它可以在容器内部直接构造键值对,避免额外的拷贝操作,效率更高:void addElement(const QString& elementName, const TYPE& T) { unorderedMultiMap.emplace(elementName, T); }
问题2:迭代器typedef的错误
你当前的迭代器typedef写死了QString作为值类型,这和模板类的TYPE参数完全矛盾,自然会报错。正确的写法是让迭代器类型和成员变量unorderedMultiMap的类型保持一致,也就是用模板参数TYPE作为值类型:
typedef typename std::unordered_multimap<QString, TYPE>::iterator iterator; typedef typename std::unordered_multimap<QString, TYPE>::const_iterator const_iterator; // 建议补充const迭代器,适配const成员函数
这里的typename是必须的,因为std::unordered_multimap<QString, TYPE>::iterator是一个依赖于模板参数TYPE的类型,编译器需要typename来明确这是一个类型,而非静态成员变量。
另外,你的isElementInMap是const成员函数,但返回普通iterator会导致编译错误——const容器只能返回const_iterator。所以需要调整返回类型,或者重载一个非const版本:
// const版本,适配const对象调用 const_iterator isElementInMap(const QString& elementName) const { return unorderedMultiMap.find(elementName); } // 可选:非const版本,适配非const对象调用 iterator isElementInMap(const QString& elementName) { return unorderedMultiMap.find(elementName); }
修正后的完整代码
整合所有修改后,你的模板类应该是这样的:
#include <unordered_map> #include <QString> template<class TYPE> class MapTemplate { public: typedef typename std::unordered_multimap<QString, TYPE>::iterator iterator; typedef typename std::unordered_multimap<QString, TYPE>::const_iterator const_iterator; void addElement(const QString& elementName, const TYPE& T) { // 推荐用emplace,更高效 unorderedMultiMap.emplace(elementName, T); // 或者用自动推导的make_pair: // unorderedMultiMap.insert(std::make_pair(elementName, T)); } std::pair<iterator, iterator> getEqual_range(const QString& elementName) { return unorderedMultiMap.equal_range(elementName); } // 补充const版本的equal_range std::pair<const_iterator, const_iterator> getEqual_range(const QString& elementName) const { return unorderedMultiMap.equal_range(elementName); } int removeElement(const QString& elementName) { return unorderedMultiMap.erase(elementName); } int getNumberOfElements() const { return unorderedMultiMap.size(); } bool isMapEmpty() const { return unorderedMultiMap.empty(); // 注意:std容器用empty(),isEmpty()是Qt容器的方法 } const_iterator isElementInMap(const QString& elementName) const { return unorderedMultiMap.find(elementName); } iterator isElementInMap(const QString& elementName) { return unorderedMultiMap.find(elementName); } private: std::unordered_multimap<QString, TYPE> unorderedMultiMap; };
额外提个小细节:std::unordered_multimap的空判断方法是empty(),不是isEmpty()——isEmpty()是Qt容器(比如QMap)的成员函数,你之前的代码里调用unorderedMultiMap.isEmpty()会报错,已经帮你修正了。
内容的提问来源于stack exchange,提问作者Jules

