【问题标题】:Overloading operator== for const std::reference_wrapper in std::unordered_map为 std::unordered_map 中的 const std::reference_wrapper 重载 operator==
【发布时间】:2015-12-16 17:01:19
【问题描述】:

我不知道如何使用std::reference_wrapperstd::string 引用引用到std::unordered_map。根据以下链接,我知道我需要重载operator==

Why can template instances not be deduced in `std::reference_wrapper`s?

但是,我不知道如何编写 operator== 以使其需要 const std::reference_wrapper。如果 wrapper 不是 const 就不会有问题。

使用 char 代替 std::string 可以正常工作(不需要重载 operator==)。

代码:

#include <iostream>
#include <unordered_map>
#include <functional>

bool operator==(const std::reference_wrapper<std::string> lhs,
                const std::reference_wrapper<std::string> rhs)
{
    return std::equal_to<std::string>()(lhs.get(), rhs.get());
}

int main(){
    char        chr('a');
    std::string str("b");
    int         num(1);

    // this works (char)
    std::unordered_map<std::reference_wrapper<char>, int, std::hash<char>> charMap;
    std::pair<std::reference_wrapper<char>, int> charPair(chr , num);
    charMap.insert(charPair);
    std::cout << "charMap works.  Output: " << charMap[chr] << std::endl;

    // does not work (std::string)
    std::unordered_map<std::reference_wrapper<std::string>, int, std::hash<std::string>> stringMap;
    std::pair<std::reference_wrapper<std::string>, int> stringPair(str , num);
    stringMap.insert(stringPair);  // compile error
}

编译错误:

error: no match for ‘operator==’ (operand types are ‘const std::reference_wrapper<std::__cxx11::basic_string<char> >’ and ‘const std::reference_wrapper<std::__cxx11::basic_string<char> >’)
       { return __x == __y; }

【问题讨论】:

    标签: c++ c++11 stl operator-overloading reference-wrapper


    【解决方案1】:

    您不能为非用户定义类型的operator== 提供自己的重载。也就是说,充其量是未定义的行为。但是,您不需要在此处执行此操作。 std::unordered_map五个模板参数:

    template<
        class Key,
        class T,
        class Hash = std::hash<Key>,
        class KeyEqual = std::equal_to<Key>,
        class Allocator = std::allocator< std::pair<const Key, T> >
    > class unordered_map;
    

    看到第四个了吗?那就是你想要的。您需要提供一个函数进行比较。幸运的是,您可以像这样使用 std::hash 和 std::equal_to:

    std::unordered_map<
        std::reference_wrapper<std::string>,
        int,
        std::hash<std::string>,
        std::equal_to<std::string>
    > stringMap;
    

    【讨论】:

    • 是的,这是正确的解决方案。不幸的是,std::reference_wrapper 没有指定operator==(很容易将其转发到底层类型的operator==)并且也没有提供散列方法。因此,在使用这些创建 unordered_mapunordered_set 时,必须始终明确。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-15
    • 2020-02-09
    • 1970-01-01
    相关资源
    最近更新 更多