Подтвердить что ты не робот

Специализация шаблона и проблемы с enable_if

У меня возникла проблема с соответствующим использованием enable_if и специализацией шаблона.

После изменения примера (по причинам конфиденциальности), здесь сопоставимый пример:

У меня есть функция, называемая "less", которая проверяет, является ли первый arg меньше, чем 2 Arg. Скажем, я хочу иметь 2 разных вида реализации в зависимости от типа ввода - 1 реализация для целых и другой для двойного.

Код, который у меня до сих пор выглядит следующим образом:

#include <type_traits>
#include <iostream>

template <class T,
          class = typename std::enable_if<std::is_floating_point<T>::value>::type>
     bool less(T a, T b) {
  // ....
}

template <class T,
          class = typename std::enable_if<std::is_integral<T>::value>::type>
     bool less(T a, T b) {
  // ....
}

int main() {
    float a;
    float b;
    less(a,b);
    return 0;
}

Вышеприведенный код не компилируется, потому что - он говорит, что я переопределяю метод less.

Ошибки:

Z.cpp:15:19: error: template parameter redefines default argument
          class = typename std::enable_if<std::is_integral<T>::value>::type>

                  ^
Z.cpp:9:19: note: previous default template argument defined here
          class = typename std::enable_if<std::is_floating_point<T>::value>::type>
                  ^

Z.cpp:16:11: error: redefinition of 'less'
     bool less(T a, T b) {
          ^

Z.cpp:10:11: note: previous definition is here
     bool less(T a, T b) {
          ^

Z.cpp:23:5: error: no matching function for call to 'less'
    less(a,b);
    ^~~~

Z.cpp:15:43: note: candidate template ignored: disabled by 'enable_if'
      [with T = float]
          class = typename std::enable_if<std::is_integral<T>::value>::type>
                                          ^
3 errors generated.

Может кто-нибудь указать, что здесь ошибка?

4b9b3361

Ответ 1

Аргументы шаблона по умолчанию не являются частью сигнатуры шаблона функции. Поэтому в вашем примере у вас есть две идентичные перегрузки less, что является незаконным. clang жалуется на переопределение аргумента по умолчанию (что также является незаконным в соответствии с §14.1/12 [temp.param]), а gcc вызывает следующее сообщение об ошибке:

ошибка: переопределение "template<class T, class> bool less(T, T)"

Чтобы исправить ошибку, переместите выражение enable_if из аргумента по умолчанию в параметр фиктивного шаблона

template <class T,
          typename std::enable_if<std::is_floating_point<T>::value, int>::type* = nullptr>
     bool less(T a, T b) {
  // ....
}

template <class T,
          typename std::enable_if<std::is_integral<T>::value, int>::type* = nullptr>
     bool less(T a, T b) {
  // ....
}

Другой вариант - использовать enable_if в возвращаемом типе, хотя я считаю, что это труднее читать.

template <class T>
      typename std::enable_if<std::is_floating_point<T>::value, bool>::type 
      less(T a, T b) {
  // ....
}

template <class T>
     typename std::enable_if<std::is_integral<T>::value, bool>::type 
     less(T a, T b) {
  // ....
}