Title
Hashing enums should be supported directly by std::hash
Status
c++14
Section
[unord.hash]
Submitter
Ville Voutilainen

Created on 2012-04-10.00:00:00 last changed 130 months ago

Messages

Date: 2013-04-18.22:58:13

Proposed resolution:

This wording is relative to N3485.

  1. In [function.objects], header functional synopsis, edit as indicated:

    namespace std {
      […]
      // 20.8.12, hash function baseprimary template:
      template <class T> struct hash;
      […]
    }
    
  2. In [unord.hash]/1 edit as indicated:

    -1- The unordered associative containers defined in [unord] use specializations of the class template hash as the default hash function. For all object types Key for which there exists a specialization hash<Key>, and for all enumeration types ([dcl.enum]) Key, the instantiation hash<Key> shall: […]

Date: 2013-04-15.00:00:00

[ 2013-04-18, Bristol ]

Date: 2013-04-14.00:00:00

[ 2013-04-14 STL provides rationale and improved wording ]

Rationale:

This can be achieved by inserting a very small tweak to the Standardese. We merely have to require that hash<Key> be valid when Key is an "enumeration type" (which includes both scoped and unscoped enums). This permits, but does not require, hash<Enum> to behave identically to hash<underlying_type<Enum>::type>, following existing precedent — note that when unsigned int and unsigned long are the same size, hash<unsigned int> is permitted-but-not-required to behave identically to hash<unsigned long>.

This proposed resolution doesn't specify anything else about the primary template, allowing implementations to do whatever they want for non-enums: static_assert nicely, explode horribly at compiletime or runtime, etc.

While we're in the neighborhood, this proposed resolution contains an editorial fix. The [function.objects] synopsis says "base template", which doesn't appear anywhere else in the Standard, and could confuse users into thinking that they need to derive from it. The proper phrase is "primary template".

Date: 2012-10-19.07:50:57

[ 2012-10 Portland: Move to Open ]

We agree this is a real issue that should be resolved, by specifying such a hash.

It is not clear that we should specify this as calling hash on the underlying_type, or whether that is overspecification and we merely require that the hash be supplied.

STL already has shipped an implementation, and is keen to provide wording.

Date: 2012-04-10.00:00:00

The paper proposes various hashing improvements. What it doesn't mention is hashing of enums; enums are integral types, and users expect them to have built-in hashing support, rather than having to convert enums to ints for uses with unordered containers and other uses of hashes. Daniel Krügler explains in c++std-lib-32412 that this is not achievable with a SFINAEd hash specialization because it would require a partial specialization with a type parameter and a non-type parameter with a default argument, which is currently not allowed, and hence the fixes in N3333 should be adopted instead.

History
Date User Action Args
2014-02-20 13:20:35adminsetstatus: wp -> c++14
2013-04-25 19:07:07adminsetstatus: voting -> wp
2013-04-19 21:44:50adminsetstatus: ready -> voting
2013-04-18 22:58:13adminsetmessages: + msg6455
2013-04-18 22:58:13adminsetstatus: open -> ready
2013-04-13 15:51:38adminsetmessages: + msg6448
2013-04-13 15:51:38adminsetmessages: + msg6447
2012-10-19 07:50:57adminsetmessages: + msg6186
2012-10-19 07:50:57adminsetstatus: new -> open
2012-04-10 00:00:00admincreate