C ++模板函数实现不正确

时间:2015-09-23 12:51:14

标签: c++ function templates sfinae enable-if

我在这里实现了这个功能(在单个头文件中)。

//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>使用decl。 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>
    >

所以我的问题是......第二个typename代表什么?

2 个答案:

答案 0 :(得分:3)

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

Live Example

注意enable_if_t<T>typename enable_if<T>::type的类型别名,可在C ++ 14中找到(您可以自己编写)

答案 1 :(得分:2)

  

在这种情况下,它没有编译......所以如何处理这个?

再次考虑您的模板:

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) { ... }

同样适用于其他情况。