std::unordered_map::emplace返回类型显式声明错误,求正确写法
模板类中std::unordered_map::emplace返回值的显式类型声明问题
问题代码
#include <iostream> #include <unordered_map> template<class T> class MSet { public: std::unordered_map<T, int> map; MSet(): map(std::unordered_map<T, int>()) {}; void add(T e); }; template<class T> void MSet<T>::add(T e) { std::pair<std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1); if (ret.second) { std::cout << "Added" << std::endl; } } int main(int, char**){ MSet<int> mset; mset.add(1); }
编译错误信息
[build] /home/experiment/main.cpp: In member function ‘void MSet<T>::add(T)’: [build] /home/experiment/main.cpp:14:57: error: type/value mismatch at argument 1 in template parameter list for ‘template<class _T1, class _T2> struct std::pair’ [build] std::pair<std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1); [build] ^ [build] /home/experiment/main.cpp:14:57: note: expected a type, got ‘std::unordered_map<T, int>::iterator’ [build] /home/experiment/main.cpp:15:13: error: request for member ‘second’ in ‘ret’, which is of non-class type ‘int’ [build] if (ret.second) { [build] ^~~~~~ [build] /home/experiment/main.cpp: In instantiation of ‘void MSet<T>::add(T) [with T = int]’: [build] /home/experiment/main.cpp:23:15: required from here [build] /home/experiment/main.cpp:14:59: error: cannot convert ‘std::pair<std::__detail::_Node_iterator<std::pair<const int, int>, false, false>, bool>’ to ‘int’ in initialization [build] std::pair<std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1); [build] ^~~
解决方案
问题原因
在模板类的成员函数中,std::unordered_map<T, int>::iterator是依赖于模板参数T的类型,编译器在模板实例化前无法确定它是一个类型还是静态成员变量/常量,因此必须用typename关键字显式告知编译器这是一个类型。
正确的显式类型声明写法
直接修改类型声明,添加typename关键字:
template<class T> void MSet<T>::add(T e) { typename std::pair<typename std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1); if (ret.second) { std::cout << "Added" << std::endl; } }
更清晰的写法(推荐)
通过using定义类型别名,提升代码可读性:
template<class T> void MSet<T>::add(T e) { using MapType = std::unordered_map<T, int>; using EmplaceResult = typename std::pair<typename MapType::iterator, bool>; EmplaceResult ret = map.emplace(e, 1); if (ret.second) { std::cout << "Added" << std::endl; } }
当然,auto是最简洁的方式,编译器会自动推导正确的返回类型,这也是C++11及以后推荐的写法。
内容的提问来源于stack exchange,提问作者Trams
相关产品推荐
相关产品推荐

