3

Code pasted below:

auto myComp = []( std::array<const string, 3> &a, std::array<const string, 3> &b )
{
    if ( a[0] == b[0] && a[1] == b[1] && a[2] == b[2] ) {
        return true;
    } else {
        return false;
    }
};
auto myHash = []( std::array<const string, 3> &a )
{
    return std::hash<std::string>()( a[0] )
    ^ std::hash<std::string>()( a[1] )
    ^ std::hash<std::string>()( a[2] );
};
std::unordered_set<std::array<const string, 3>, decltype( myHash ), decltype( myComp )> unordSet( 16, myHash, myComp );

The whole error message is:

MacOSX15.1.sdk/usr/include/c++/v1/__hash_table:607:17 Static assertion failed due to requirement 'integral_constant<bool, false>::value': the specified hash does not meet the Hash requirements

Many thanks in advance.

EDIT:

I managed to find out the definition of the check:

#ifndef _LIBCPP_CXX03_LANG
template <class _Key, class _Hash>
using __check_hash_requirements _LIBCPP_NODEBUG =
    integral_constant<bool,
                      is_copy_constructible<_Hash>::value && is_move_constructible<_Hash>::value &&
                          __invokable_r<size_t, _Hash, _Key const&>::value >;

Turns out it is this condition that fails the test:

__invokable_r<size_t, _Hash, _Key const&>::value
14
  • 1
    FWIW - gcc does accept the code, but not MSVC nor clang (see demo). Commented Nov 14, 2024 at 9:28
  • 2
    Aside: if (cond) return true; else return false; can — and should — always be replaced by return cond;. Don’t write unnecessary boilerplate code. Commented Nov 14, 2024 at 9:48
  • 2
    First argument to _Hash must accept _Key const& according to this constraint, your hash function doesn't allow const reference. Change argument to const std::array<const string, 3> &a. Not sure if the standard actually requires that or it's just the compiler invention. Commented Nov 14, 2024 at 9:55
  • 3
    @PkDrew This __invokable_r says that _Hash should be invocable with only one argument being _Key const& and it should return size_t. Your function did not allow const ref argument, because it required non-const ref. Commented Nov 14, 2024 at 10:30
  • 1
    @KonradRudolph • unless you are a contractor being paid by the KLOC. Commented Nov 14, 2024 at 12:03

1 Answer 1

2

Yes, you are right, the problem here is that unordered map accepts hashing function only with const reference key, it is necessary in order to guarantee data immutability during different actions to make the container work correctly, it is also accepted in STL library. That is

auto myComp = [](const array<const string, 3> &a, const.   array<const string, 3> &b)
{
    return (a[0] == b[0] && a[1] == b[1] && a[2] == b[2]);
};

auto myHash = [](const array<const string, 3> &a)
{
    return hash<string>()(a[0]) ^ hash<string>()(a[1]) ^ hash<string>()(a[2]);
};

I also suggest you read the book "Effective C++" by Scott Meyers (Chapter 3), which discusses the topic of effective use of const reference

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for answering. But is the regulation anywhere mentioned formally? It seems to be a compiler independent feature, any particular reason why const reference is asked?
Here are the main reasons why const is mandatory in this case: - std::hash and std::unordered_set assume that objects will not change, which is guaranteed by the use of const. - If the data could change, it could compromise the integrity of the data structure. - The use of const meets the requirements of the standard library API. In the end, the main reason is for the security and immutability of the data for the data structure to work correctly.
This rule is not mandatory at the C++ language level, but it is formally enshrined in the C++ standard library requirements for the correct functioning of containers such as std::unordered_set.
Yeah makes sense, the same way Python asks for, thanks for the explanation mate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.