我在自己的课堂上使用
std::unordered_map
。代码如下:
#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);
}
对于
ret
中的 MSet::add
类型,编译器报告以下错误:
[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::pair<std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1);
到
auto ret = map.emplace(e, 1);
并且如果替换的话编译器不会报错。我只是想找出声明类型的正确方法,以便
ret
的类型在我的代码中清晰可见。
使用 clang 编译时问题变得明显(参见 Compiler Explorer):
<source>:14:15: error: template argument for template type parameter must be a type; did you forget 'typename'?
14 | std::pair<std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1);
| ^
| typename
std::unordered_map<T, int>
依赖于T
,编译器无法判断::iterator
是映射的类型还是静态成员。要消除歧义,您需要 typename
。
写
std::pair<typename std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1);