C++ шаблонна специализация за плаващи точки

Искам да специализирам метод от клас X за типове с плаваща запетая. Следният код се компилира и работи перфектно:

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
  ...
};

x.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