Created on 2015-09-27.00:00:00 last changed 98 months ago
Proposed resolution:
This wording is relative to N4606.
Insert a new paragraph after [unord.hash]/2
[Drafting note: I see no reason to specify whether H<T> is destructible. There's no practical use case for which that would need to be covered. libstdc++ makes it so that H<T> is destructible.]
-2- The template specializations shall meet the requirements of class template hash (20.12.14).
-?- For any type T that is not of integral or enumeration type, or for which neither the library nor the user provides an explicit or partial specialization of the class template hash, the specialization of hash<T> has the following properties:
- is_default_constructible_v<hash<T>> is false
- is_copy_constructible_v<hash<T>> is false
- is_move_constructible_v<hash<T>> is false
- is_copy_assignable_v<hash<T>> is false
- is_move_assignable_v<hash<T>> is false
- hash<T> is not a function object type ([function.objects])
[Note: this means that the specialization of hash exists, but any attempts to use it as a Hash will be ill-formed. — end note]
[ 2016-11-12, Issaquah ]
Resolved by P0513R0
[ 2016-09-09 Issues Resolution Telecon ]
Move to Tentatively Ready
[ 2016-08-09 Daniel reopens ]
As pointed out by Eric, the usage of is_callable is incorrect. Eric provides new wording.
[ 2016-08 - Chicago ]
Thurs AM: Moved to Tentatively Ready
Previous resolution [SUPERSEDED]:This wording is relative to N4606.
Insert a new paragraph after [unord.hash]/2
[Drafting note: I see no reason to specify whether H<T> is destructible. There's no practical use case for which that would need to be covered. libstdc++ makes it so that H<T> is destructible.]
-2- The template specializations shall meet the requirements of class template hash (20.12.14).
-?- For any type T that is not of integral or enumeration type, or for which neither the library nor the user provides an explicit or partial specialization of the class template hash, the specialization of hash<T> has the following properties:
- is_default_constructible_v<hash<T>> is false
- is_copy_constructible_v<hash<T>> is false
- is_move_constructible_v<hash<T>> is false
- is_copy_assignable_v<hash<T>> is false
- is_move_assignable_v<hash<T>> is false
- is_callable_v<hash<T>, T&> is false
- is_callable_v<hash<T>, const T&> is false
[Note: this means that the specialization of hash exists, but any attempts to use it as a Hash will be ill-formed. — end note]
[ 2016-06-14, Daniel comments ]
The problematic part of the P/R is that it describes constraints that would be suitable if they were constraints
for user-code, but they are not suitable as requirements imposed on implementations to provide certain guarantees
for clients of the Library. The guarantees should be written in terms of testable compile-time expressions, e.g. based on
negative results of is_default_constructible<hash<X>>::value,
std::is_copy_constructible<hash<X>>::value, and possibly also
std::is_destructible<hash<X>>::value. How an implementation realizes these negative
results shouldn't be specified, though, but the expressions need to be well-formed and well-defined.
This wording is relative to N4582.
Insert a new paragraph after [unord.hash]/2
-2- The template specializations shall meet the requirements of class template hash (20.12.14).
-?- For any type that is not of integral or enumeration type, or for which neither the library nor the user provides an explicit specialization of the class template hash, the specialization of hash does not meet any of the Hash requirements, and is not DefaultConstructible nor MoveAssignable. [Note: this means that the specialization of hash exists, but any attempts to use it as a Hash will be ill-formed. — end note]
[ 2016-05-25, Tim Song comments ]
I see two issues with this P/R:
"for which neither the library nor the user provides an explicit specialization" should probably be "for which neither the library nor the user provides an explicit or partial specialization".
Saying that the specialization "is not DefaultConstructible nor MoveAssignable" is not enough to guarantee that common SFINAE uses will work. Both of those requirements have several parts, and it's not too hard to fail only some of them. For instance, not meeting the assignment postcondition breaks MoveAssignable, but is usually not SFINAE-detectible. And for DefaultConstructible, it's easy to write something in a way that breaks T() but not T{} (due to aggregate initialization in the latter case).
[ 2016-05-08, Eric Fiselier & Ville provide wording ]
[ 2015-10, Kona Saturday afternoon ]
EricWF to come back with wording; move to Open
The rationale in issue 2148 says:
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.
libc++ seems to implement it by defining the primary template and static_asserting is_enum inside it. However, that brings forth a problem; there are reasonable SFINAE uses broken by it:
#include <type_traits> #include <functional> class S{}; // No hash specialization template<class T> auto f(int) -> decltype(std::hash<T>(), std::true_type()); template<class T> auto f(...) -> decltype(std::false_type()); static_assert(!decltype(f<S>(0))::value, "");
MSVC doesn't seem to accept that code either.
There is a way to implement LWG 2148 so that hash for enums is supported without breaking that sort of SFINAE uses:Derive the main hash template from a library-internal uglified-named base template that takes a type and a bool, pass as argument for the base the result of is_enum.
Partially specialize that base template so that the false-case has a suitable set of private special member function declarations so that it's not an aggregate nor usable in almost any expression.
History | |||
---|---|---|---|
Date | User | Action | Args |
2016-11-21 17:34:16 | admin | set | messages: + msg8679 |
2016-11-21 17:34:16 | admin | set | status: wp -> resolved |
2016-11-14 03:59:28 | admin | set | status: pending -> wp |
2016-11-14 03:55:22 | admin | set | status: ready -> pending |
2016-09-12 04:46:33 | admin | set | messages: + msg8515 |
2016-09-12 04:46:33 | admin | set | status: open -> ready |
2016-08-09 20:35:14 | admin | set | messages: + msg8464 |
2016-08-09 20:35:14 | admin | set | status: ready -> open |
2016-08-05 03:33:05 | admin | set | messages: + msg8413 |
2016-08-05 03:33:05 | admin | set | status: open -> ready |
2016-06-14 21:01:34 | admin | set | messages: + msg8176 |
2016-06-14 21:01:34 | admin | set | messages: + msg8175 |
2016-05-11 20:17:52 | admin | set | messages: + msg8119 |
2016-05-11 20:17:52 | admin | set | messages: + msg8118 |
2015-11-04 16:49:21 | admin | set | messages: + msg7616 |
2015-11-04 16:49:21 | admin | set | status: new -> open |
2015-09-27 00:00:00 | admin | create |