0
\$\begingroup\$

Is there something terribly wrong with this implementation?

template <class T>
constexpr inline std::size_t hash_combine(T const& v,
  std::size_t const seed = {}) noexcept
{
  return seed ^ (std::hash<T>()(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2));
}

template <typename T> struct hash;

template <typename ...T>
struct hash<std::tuple<T...>>
{
  template <typename A1, typename ...A, std::size_t ...I>
  static auto apply_tuple(std::tuple<A1, A...> const& t,
    std::index_sequence<I...>) noexcept
  {
    if constexpr(sizeof...(A))
    {
      return hash_combine(std::get<0>(t),
        hash<std::tuple<A const&...>>()({std::get<I + 1>(t)...})
      );
    }
    else
    {
      return std::hash<std::remove_cv_t<std::remove_reference_t<A1>>>()(
        std::get<0>(t));
    }
  }

  auto operator()(std::tuple<T...> const& t) const noexcept
  {
    return apply_tuple(t,
      std::make_index_sequence<sizeof...(T) - 1>()
    );
  }
};

EDIT: This is better, I think:

template <typename ...T>
struct hash<std::tuple<T...>>
{
  template <std::size_t ...I>
  static auto apply_tuple(std::tuple<T...> const& t,
    std::index_sequence<I...>)
  {
    std::size_t seed{};

    return ((seed = hash_combine(std::get<I>(t), seed)), ...);
  }

  auto operator()(std::tuple<T...> const& t) const
  {
    return apply_tuple(t, std::make_index_sequence<sizeof...(T)>());
  }
};
\$\endgroup\$
  • \$\begingroup\$ Care about editing code in your question. Otherwise, I didn't notice something wrong in your code. \$\endgroup\$ – Calak Nov 4 '18 at 19:37
  • \$\begingroup\$ great, maybe you'll think of something later. \$\endgroup\$ – user1095108 Nov 4 '18 at 20:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.