Неправильная реализация функции шаблона C++

Я реализовал эту функцию здесь (в одном заголовочном файле).

//header.h
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <stdint.h>
#include <type_traits>



   template < typename T,
           typename = std::enable_if<std::is_integral<T> >::type >
void f(T t) {
    printf("Integer function\n");
}

template void f(int i);

Основное ниже...

#include "header.h"
int main(int argc, char** argv) {
    int p = 3;
    f(p);
}

Он компилируется... не проблема, но он не показывает содержимое printf, что мне не хватает?... (я использую eclipse в качестве IDE, это может быть проблемой?)

Еще одна вещь... имеет ли смысл эту реализацию? (Я хотел бы написать другой код в зависимости от типа ввода, независимо от того, является ли он без знака или нет).

template < typename T,
           typename = std::enable_if<std::is_integral<T>::value>,
           typename = std::enable_if<std::is_unsigned<T>::value>
>
void f(T t) {
    printf("Unsigned f version.\n");
}

template < typename T,
           typename = std::enable_if<std::is_integral<T>::value>,
           typename = std::enable_if<std::is_signed<T>::value>
>
void f(T t) {
    printf("Signed f version.\n");
}

В этом случае он не компилируется... так как с этим бороться?

Спасибо

Обновить...

Я попробовал модификацию, предложенную в первом коде, она дает мне следующую ошибку

..\header.h:19:58: error: type/value mismatch at argument 1 in template parameter list for 'template<bool <anonymous>, class _Tp> struct std::enable_if'
            typename = std::enable_if<std::is_integral<T> >::type >
                                                          ^
..\header.h:19:58: error:   expected a constant of type 'bool', got 'std::is_integral<_Tp>'
..\header.h:19:61: error: expected '>' before 'type'
            typename = std::enable_if<std::is_integral<T> >::type >
                                                             ^
..\main.cc: In function 'int main(int, char**)':

Обновление 2...

Хорошо, ребята... Я пытался выяснить, что это такое, я не понимаю... поэтому я копаюсь в коде type_traits (поэтому моя цель - понять, что я сделал неправильно...)

Я сообщаю код для enable_if (из type_traits).

template<bool, typename _Tp = void>
    struct enable_if //Lukkio decl. 1
    { };

  // Partial specialization for true.
  template<typename _Tp>
    struct enable_if<true, _Tp> //Lukkio decl. 2
    { typedef _Tp type; };

Потому что я хочу понять, что происходит с такой строкой:

template<
    typename T,
    typename = std::enable_if<std::is_integral<T>::value>
>
void function(T t) {
    printf("Is integral!\n");
}

Так предполагая T фиксированный (скажем, int, который является интегрированным) std::enable_if::value> используйте декл. 1, если, однако, _Tp имеет тип void так на самом деле, что происходит, с точки зрения сокращения (теперь я заменяю T ключевое слово int... должно быть что-то вроде

template<
        typename int,
        typename = std::enable_if<std::is_integral<int>::value>
    >

а именно

template<
        typename int,
        typename = std::enable_if<1>
    >

Итак, мой вопрос... что означает второе имя типа?

2 ответа

Решение

SFINAE для аргументов шаблона функции по умолчанию не масштабируется. Вы можете использовать это, только если вы хотите ограничить одну перегрузку определенным классом типов.

Для неперекрывающихся множественных перегрузок (таких как ваши интегралы со знаком / без знака) вы можете SFINAE для возвращаемого типа следующим образом:

#include <cstdio>
#include <type_traits>

template < typename T>
auto f(T t) 
    -> std::enable_if_t<std::is_unsigned<T>::value && std::is_integral<T>::value>
{
    printf("Unsigned f version.\n");
}

template < typename T>
auto f(T t) 
    -> std::enable_if_t<std::is_signed<T>::value && std::is_integral<T>::value>
{
    printf("Signed f version.\n");
}

int main()
{
    unsigned u = 1;
    signed s = 1;
    f(u);
    f(s);
}

Живой пример

Примечание: enable_if_t<T> это псевдоним типа для typename enable_if<T>::type который появился в C++14 (вы можете написать его самостоятельно)

В этом случае он не компилируется... так как с этим бороться?

Рассмотрим ваши шаблоны еще раз:

template < typename T,
           typename = std::enable_if<std::is_integral<T>::value>,
           typename = std::enable_if<std::is_unsigned<T>::value>
>
void f(T t) {

Вы на самом деле не используете SFINAE. Ваши безымянные типы просто std::enable_if<X>, Это всегда допустимый тип. Для того, чтобы SFINAE подала заявку, вам нужно добавить ::type в конце или использовать std::enable_if_t, то есть:

template < typename T,
           typename = std::enable_if_t<std::is_integral<T>::value>,
           typename = std::enable_if_t<std::is_unsigned<T>::value>
>
void f(T t) {

Теперь вы столкнетесь с двумя неоднозначными шаблонами функций, которые вы можете устранить, используя enable_if_t как значение вместо типа. То есть:

template < typename T,
           std::enable_if_t<std::is_integral<T>::value &&
                            std::is_unsigned<T>::value>* = nullptr
           >
void f(T t) { ... }

И аналогично для другого случая.

Другие вопросы по тегам