2015-09-19 5 views
3

Я не могу понять, как получить ссылку std::string в std::unordered_map, используя std::reference_wrapper. По следующей ссылке я понимаю, что мне нужно перегрузить operator==.Оператор перегрузки == для const std :: reference_wrapper в std :: unordered_map

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

Однако, я не могу понять, как писать operator== таким образом, что он будет принимать сопзЬstd::reference_wrapper. Если обертка не была const, это не было бы проблемой.

Использование символа вместо 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; } 

ответ

5

Вы не можете создать собственную перегрузку 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; 

См 4-й один? Это то, что ты хочешь. Вам нужно предоставить функцию для сравнения. К счастью, вы можете использовать std :: hash и std :: equal_to примерно так:

std::unordered_map< 
    std::reference_wrapper<std::string>, 
    int, 
    std::hash<std::string>, 
    std::equal_to<std::string> 
> stringMap; 
Смежные вопросы