返回类型 'std::unordered_map::emplace' [duplicate]

Return type of `std::unordered_map::emplace` [duplicate]

提问人:Trams 提问时间:9/5/2023 更新时间:9/5/2023 访问量:47

问:

我在我自己的班级中使用。代码如下所示: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);
}

编译器报告以下类型的错误:retMSet::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);

如果替换,编译器将不会报告错误。我只是想找出声明类型的正确方法,以便在我的代码中明确 of 的类型。ret

C++ C++11 STL 无序映射

评论

0赞 BoP 9/5/2023
可以说不是很清楚... :-)std::pair<typename std::unordered_map<T, int>::iterator, bool>

答:

2赞 Jan Schultke 9/5/2023 #1

使用 clang 进行编译时,问题变得很明显(请参阅编译器资源管理器):

<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>依赖于 ,编译器无法判断是 map 的类型成员还是静态成员。为了消除歧义,您需要 .T::iteratortypename

写:

std::pair<typename std::unordered_map<T, int>::iterator, bool> ret = map.emplace(e, 1);

请注意,从风格上讲,在这里使用更好;否则,你最终会得到一个很长的类型,读者很清楚结果必须是什么。 在 C++17 中,您还可以使用结构化绑定:autoemplace

auto [pos, success] = map.emplace(e, 1); // C++17

另请参阅我必须在哪里以及为什么必须放置“template”和“typename”关键字?