Специализация класса шаблона с различными концепциями приводит к ошибке переопределения

#c #c 20 #template-specialization #c -concepts

Вопрос:

Я пишу некоторый код, используя std::hash и Hashable концепцию. Однако я не могу определить специализации с помощью двух разных понятий, даже если у меня нет их двусмысленного экземпляра.

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

namespace ranges = std::ranges;

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

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

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

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

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

template <Hashable T>
static size_t Hash(const Tamp; 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

Я бы понял эту ошибку , если бы существовал класс, который одновременно является HashableRange и HashableWithMember а, и а, но его нет. Почему это не работает?

Комментарии:

1. Похоже на ошибку .

2. Я так думаю. Взглянув еще раз, я понял, что это работает, если я включу специализации в явном namespace std виде : godbolt.org/z/h9811vEEe Преступник, похоже, специализируется на них с struct std::hash помощью синтаксиса.

Ответ №1:

Это известная ошибка GCC [concepts] redefinition error when using constrained structure template inside namespace : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92944

Более простой пример выглядит следующим образом:

 #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 и MSVC с этим согласны, ошибка только в GCC. Демо: https://gcc.godbolt.org/z/Warhfaf7q