2015-03-31 4 views
7

Я думал, что это было бы, но я не могу найти это в своей стандартной библиотечной реализации (gcc-4.8.2).Почему std :: hash не специализируется на std :: reference_wrapper?

Почему std::hash еще не специализировался на std::reference_wrapper?

#pragma once 
#include <functional> 

namespace std 
{ 
    template<typename T> 
    struct hash<reference_wrapper<T>> 
    { 
     size_t operator()(const reference_wrapper<T>& r) const 
     { 
      return std::hash<T>()(r.get()); 
     } 
    }; 
} 
+3

Возможно, потому что, если у вас есть контейнер ссылочных оберток, неясно, должно ли оно хешировать ссылки или референты, и предоставление стандартной специализации должно было бы выбрать один и при этом путать людей. Поскольку это не предусмотрено, вы вынуждены делать свое намерение явным. – Brian

+0

Если не ссылка, на что бы вы ссылались: 'reference_wrapper'? Это только член 'get()', который возвращает 'T &' (и оператор вызова функции, который делает то же самое). Он существует почти исключительно для того, чтобы ссылки хранились в стандартных контейнерах. –

+1

Указатель, * i.e. *, 'std :: addressof (r.get())'. – Brian

ответ

2

std::reference_wrapper в основном используется для обеспечения эталонных семантик в утилите, которые по умолчанию копирования значений, такие как std::bind.

Прямое использование std::reference_wrapper как в контейнере по существу похоже на указатель (за исключением того, что он не может быть недействительным). Хеширование указателей (и интеллектуальных указателей) следует за семантикой ссылки (т. Е. Адреса).

Вы всегда можете предоставить свою собственную функцию хэша, конечно. Если вы определяете его как шаблон по всем указателям и интеллектуальным указателям, то T* может быть лучшим выбором типа значения, а не reference_wrapper<T>.

Обратите внимание, что если вы уже используете хеширующие объекты и сохраняете хеши, вы можете устранить дубликаты, сохранив все в unordered_map. Тогда значение идентификатора и идентификатора объекта будет одинаковым.