2015-09-23 244 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