This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3 PATCH] Make poisoned hashes SFINAE away the call operator of the hash.


Tested on Linux-x64. The approach is a bit ugly, the hashes derive
from __poison_hash and also use its nested __enable_hash_call as
an argument for another utility base. I prototyped various approaches
to try to decrease that duplication, but didn't like any of them (more
utility bases, aliases, even passing a lambda that does the concrete
hash to a more generic hash in a base), and they certainly didn't make
the code any shorter.

The reason this patch was done is that K-ballo pointed out that
our hashes have a non-SFINAED call operator that uses a constructing-expression
in its noexcept-spec - so asking is_callable from a poisoned hash leads
to a hard error, including in cases where the user would correctly
check both callability and constructibility, but in that order. I steered
away from turning the call operators into constrained templates, and
chose a conditional base approach instead, because that keeps functions
as functions instead of turning them into templates; we do not want
to open the possibility that a caller starts providing template arguments
explicitly.

This patch covers unique_ptr, std::optional and std::variant. We might
want to entertain doing this for std::experimental::optional as well.

2017-01-20  Ville Voutilainen  <ville.voutilainen@gmail.com>

    Make poisoned hashes SFINAE away the call operator
    of the hash.
    * include/bits/functional_hash.h
    (__poison_hash::__enable_hash_call): New.
    * include/bits/unique_ptr.h (__unique_ptr_hash_call_base): New.
    (hash<unique_ptr<_Tp, _Dp>>): Derive from the new base,
    move the hash function into that base, use the added enabling
    flag to SFINAE.
    * include/std/optional (__optional_hash_call_base): New.
    (hash<optional<_Tp>>): Derive from the new base,
    move the hash function into that base, use the added enabling
    flag to SFINAE.
    * include/std/variant(__variant_hash_call_base): New.
    (hash<variant<_Types...>>): Derive from the new base,
    move the hash function into that base, use the added enabling
    flag to SFINAE.
    * testsuite/20_util/optional/hash.cc: Add tests for is_callable.
    * testsuite/20_util/unique_ptr/hash/1.cc: Likewise.
    * testsuite/20_util/variant/hash.cc: Likewise.

Attachment: is_hash_callable.diff
Description: Text document


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]