Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Template class specialization with different concepts gives redefinition error

I'm writing some code using std::hash and a Hashable concept. However I can't define specializations with two different concepts even if I don't have an ambiguous instance of them.

#include <ranges>
#include <concepts>
#include <functional>

namespace ranges = std::ranges;

template <typename T>
concept Hashable = requires(const T& t) {
  { std::hash<T>{}(t) } -> std::convertible_to<size_t>;
};

template <typename T>
concept HashableWithMember = requires(const T& t) {
  { t.Hash() } -> std::convertible_to<size_t>;
};

template <typename R>
concept HashableRange = ranges::range<R> && Hashable<ranges::range_value_t<R>>;

template <HashableWithMember T>
struct std::hash<T> {
  size_t operator()(const T& t) const { return t.Hash(); }
};

template <HashableRange R>
struct std::hash<R> {
  size_t operator()(const R& r) const {
    return 0;
  }
};

template <Hashable T>
static size_t Hash(const T& t) {
  return std::hash<T>{}(t);
}
<source>:26:13: error: redefinition of 'struct std::hash<_Tp>'
   26 | struct std::hash<R> {
      |             ^~~~~~~
<source>:21:13: note: previous definition of 'struct std::hash<_Tp>'
   21 | struct std::hash<T> {
      |             ^~~~~~~

https://godbolt.org/z/1roj1qMbs

I would understand this error if there were a class which is both a HashableRange and a HashableWithMember, but there isn't. Why doesn't this work?

like image 419
ofo Avatar asked Nov 07 '22 00:11

ofo


1 Answers

This is known GCC bug [concepts] redefinition error when using constrained structure template inside namespace: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92944

A simpler example is as follows:

#include <concepts>
#include <functional>

template <std::convertible_to<int> T>
struct std::hash<T> {};

template <std::convertible_to<float> U>
struct std::hash<U> {};

Clang and MSVC are ok with it, the bug is GCC only. Demo: https://gcc.godbolt.org/z/Warhfaf7q

like image 163
Fedor Avatar answered Nov 14 '22 22:11

Fedor