Специализация шаблона C++ для работы с плавающей запятой

Я хочу специализировать метод класса X для типов с плавающей запятой. Следующий код компилируется и работает отлично:

х.hpp:

template <typename T>
class X {
 public:
  ...
  T bucket_width(const BucketID index) const;
  T bucket_min(const BucketID index) const;
  T bucket_max(const BucketID index) const
  ...
};

х.cpp:

...

template <typename T>
T X<T>::bucket_width(const BucketID index) const {
  return bucket_max(index) - bucket_min(index) + 1;
};

template <>
float X<float>::bucket_width(const BucketID index) const {
  return bucket_max(index) - bucket_min(index);
};

template <>
double X<double>::bucket_width(const BucketID index) const {
  return bucket_max(index) - bucket_min(index);
};

...

Теперь, аналогично этому ответу, я изменил файл cpp на:

template <typename T>
T X<T>::bucket_width(const BucketID index) const {
  return bucket_max(index) - bucket_min(index) + 1;
};

template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, T> X<T>::bucket_width(const BucketID index) const {
  return bucket_max(index) - bucket_min(index);
};

К сожалению, это приводит к следующей ошибке компилятора:

.../x.cpp:46:56: error: return type of out-of-line definition of 'X::bucket_width' differs from that in the declaration
std::enable_if_t<std::is_floating_point_v<T>, T> X<T>::bucket_width(const BucketID index) const {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~                       ^

Может ли кто-нибудь объяснить мне, что мне не хватает?
Заранее спасибо!

Редактировать: мы явно создаем экземпляры классов шаблонов в конце файла cpp, чтобы мы могли выполнять код шаблона в файле cpp.


person Tim Zimmermann    schedule 24.05.2018    source источник
comment
Вы не должны разделять шаблон в файле заголовка и cpp: stackoverflow.com/questions/495021/   -  person NathanOliver    schedule 24.05.2018
comment
Сообщение об ошибке выглядит так, как будто ваше объявление X::bucket_width не содержит часть enable_if, которую вы добавили в определение.   -  person Ron Kluth    schedule 24.05.2018
comment
@RonKluth Как мне правильно добавить часть enable_if в объявление?   -  person Tim Zimmermann    schedule 24.05.2018


Ответы (1)


Может кто-нибудь объяснить мне, что мне не хватает?

Ошибка объясняет это:

.../x.cpp:46:56: ошибка: возвращаемый тип внестрочного определения 'X::bucket_width' отличается от указанного в объявлении

То есть функция объявлена ​​как возвращающая T, но вы определяете ее так, чтобы она возвращала std::enable_if_t<std::is_floating_point_v<T>, T>. Они не совпадают и должны быть.

В более общем смысле вы пытаетесь частично специализировать шаблон функции, что невозможно.

Простое решение здесь — использовать if constexpr:

template <typename T>
T X<T>::bucket_width(const BucketID index) const {
  if constexpr (std::is_floating_point_v<T>) {
    return bucket_max(index) - bucket_min(index);
  } else {
    return bucket_max(index) - bucket_min(index) + 1;
  }
};
person Barry    schedule 24.05.2018