2015-09-23 123 views
1

我已经在这里实现了这个函数(在一个头文件中)。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,它是Integrale的)的std::enable_if::value>使用DECL。 1,但是假设_Tpvoid型所以实际上发生了什么,在还原条件(我现在替代到T关键字int ......应该是这样的

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

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

所以我的问题是......第二个类型名称代表什么?

+3

'std :: enable_if_t'或'std :: enable_if <..> :: type' – Columbo

+0

感谢您的回答@Columbo,有什么区别? – user8469759

+0

为什么在'header.h'中声明'template void f(int i);'? – CinCout

回答

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提供(可以自己写)

+0

你在最后加入'void'的原因是什么?只是为了明确返回类型? – TartanLlama

+0

@TartanLlama正确,无论如何默认为'void',但如果'f(T)'必须返回'int',那么你必须明确。谢谢。 – TemplateRex

+0

这个箭头的语法...这是我第一次看到它。无论如何我都会尝试。 – user8469759

2

In t他的情况它不编译...所以如何处理这个?

再次考虑您的模板:

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

对于其他情况也是类似的。

+0

啊不错,从来没有尝试过之前,相同的默认值,upvoted – TemplateRex

+0

这很复杂...从来没有使用过这个东西之前...有我不知道...一种参考,解释如何使用这个新的C++功能(当然是新的...)?我认为这是更直接的申请。 – user8469759

+0

@Lukkio只需浏览一堆关于这个问题的:) :) – Barry