This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of C++11 status.
std::hash<string> & coSection: 22.10.19 [unord.hash] Status: C++11 Submitter: Paolo Carlini Opened: 2009-10-22 Last modified: 2016-01-28
Priority: Not Prioritized
View all other issues in [unord.hash].
View all issues with C++11 status.
Discussion:
In 22.10.19 [unord.hash], operator() is specified as
taking the argument by value. Moreover, it is said that operator() shall
not throw exceptions.
However, for the specializations for class types, like string,
wstring, etc, the former requirement seems suboptimal from the
performance point of view (a specific PR has been filed about this in the GCC Bugzilla)
and, together with the latter requirement, hard if not impossible to
fulfill. It looks like pass by const reference should be allowed in such
cases.
[ 2009-11-18: Ganesh updates wording. ]
I've removed the list of types for which
hashshall be instantiated because it's already explicit in the synopsis of header<functional>in 22.10 [function.objects]/2.
[ 2009-11-18: Original wording here: ]
Add to 22.10.19 [unord.hash]/2:
namespace std { template <class T> struct hash : public std::unary_function<T, std::size_t> { std::size_t operator()(T val) const; }; }The return value of
operator()is unspecified, except that equal arguments shall yield the same result.operator()shall not throw exceptions. It is also unspecified whetheroperator()ofstd::hashspecializations for class types takes its argument by value or const reference.
[ 2009-11-19 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
[ 2009-11-24 Ville Opens: ]
I have received community requests to ask for this issue to be reopened. Some users feel that mandating the inheritance is overly constraining.
[ 2010-01-31 Alisdair: related to 978(i) and 1182(i). ]
[ 2010-02-07 Proposed resolution updated by Beman, Daniel and Ganesh. ]
[ 2010-02-09 Moved to Tentatively Ready after 5 positive votes on c++std-lib. ]
Proposed resolution:
Insert a new subclause either before or after the current 16.4.4.6 [allocator.requirements]:
HashRequirements [hash.requirements]This subclause defines the named requirement
Hash, used in several clauses of the C++ standard library. A typeHmeets theHashrequirement if
it is a function object type (22.10 [function.objects]).
it satisfies the requirements of
CopyConstructible, andDestructible(16.4.4.2 [utility.arg.requirements]),the expressions shown in the following table are valid and have the indicated semantics, and
it satisfies all other requirements of this subclause.
Given
Keyis an argument type for function objects of typeH, in the table belowhis a value of type (possiblyconst)H,uis an lvalue of typeKey, andkis a value of a type convertible to (possiblyconst)Key:
Table ? — HashrequirementsExpression Return type Requirement h(k)size_tShall not throw exceptions. The value returned shall depend only on the argument k. [Note: Thus all evaluations of the expressionh(k)with the same value forkyield the same result. — end note] [Note: Fort1andt2of different values, the probability thath(t1)andh(t2)compare equal should be very small, approaching(1.0/numeric_limits<size_t>::max()). — end note] Comment (not to go in WP): The wording for the second note is based on a similar note in 28.3.4.5.1.3 [locale.collate.virtuals]/3h(u)size_tShall not modify u.
Change 22.10.19 [unord.hash] as indicated:
1 The unordered associative containers defined in Clause 23.5 [unord] use specializations of the class template
hashas the default hash function. For all object typesTfor which there exists a specializationhash<T>, the instantiationhash<T>shall:
- satisfy the
Hashrequirements([hash.requirements]), withTas the function call argument type, theDefaultConstructiblerequirements ([defaultconstructible]), theCopyAssignablerequirements ([copyassignable]), and theSwappablerequirements ([swappable]),- provide two nested types
result_typeandargument_typewhich shall be synonyms forsize_tandT, respectively,- satisfy the requirement that if
k1 == k2istrue,h(k1) == h(k2)istrue, wherehis an object of typehash<T>, andk1,k2are objects of typeT.
This class template is only required to be instantiable for integer types (6.9.2 [basic.fundamental]), floating-point types (6.9.2 [basic.fundamental]), pointer types (9.3.4.2 [dcl.ptr]), andstd::string,std::u16string,std::u32string,std::wstring,std::error_code,std::thread::id,std::bitset, andstd::vector<bool>.namespace std { template <class T> struct hash : public std::unary_function<T, std::size_t> { std::size_t operator()(T val) const; }; }
2 The return value ofoperator()is unspecified, except that equal arguments shall yield the same result.operator()shall not throw exceptions.
Change Unordered associative containers 23.2.8 [unord.req] as indicated:
Each unordered associative container is parameterized by
Key, by a function object typeHash([hash.requirements]) that acts as a hash function for argument values of typeKey, and by a binary predicatePredthat induces an equivalence relation on values of typeKey. Additionally,unordered_mapandunordered_multimapassociate an arbitrary mapped typeTwith theKey.A hash function is a function object that takes a single argument of type
Keyand returns a value of typestd::size_t.Two values
k1andk2of typeKeyare considered equal if the container's equality function object returnstruewhen passed those values. Ifk1andk2are equal, the hash function shall return the same value for both. [Note: Thus supplying a non-defaultPredparameter usually implies the need to supply a non-defaultHashparameter. — end note]