2013-03-24 52 views
13

如果std::is_integral<>::value爲true,那麼我試圖返回int64_t如何使用std :: is_integral <>選擇實現?

否則,我想在對象上調用to_int64t()

我的下面的嘗試失敗,因爲功能模板的部分專業化是不允許的。

CODE

#include <type_traits> 
#include <cstdint> 

template<class T,bool is_integral_type> 
int64_t to_int64t(const T& t) 
{ 
     return t; 
} 

template<class T> 
int64_t to_int64t<T,std::is_integral<T>::value>(const T& t) 
{ 
     return t; 
} 

template<class T> 
int64_t to_int64t<T,!std::is_integral<T>::value>(const T& t) 
{ 
     return t.to_int64t(); 
} 

int main() 
{ 
     int64_t i = 64; 
     auto x = to_int64t(i); 
} 
+0

可能重複: http://stackoverflow.com/questions/12073689/c11-template-function-specialization-for-integer-types – legends2k 2013-10-03 11:53:37

回答

28

函數模板不能部分專業,在一般情況下,它是不使用函數模板專業化是個好主意。達到你想要什麼

一種方法是使用一種稱爲tag分派,基本上包含在提供選擇基於一個額外的僞參數的權值過載轉發器功能技術:

#include <type_traits> 
#include <cstdint> 

template<class T> 
int64_t to_int64t(const T& t, std::true_type) 
{ 
    return t; 
} 

template<class T> 
int64_t to_int64t(const T& t, std::false_type) 
{ 
    return t.to_int64t(); 
} 

template<class T> 
int64_t to_int64t(const T& t) 
{ 
    return to_int64t(t, std::is_integral<T>()); 
} 

int main() 
{ 
    int64_t i = 64; 
    auto x = to_int64t(i); 
} 

另一種可能性是使用基於std::enable_if的經典SFINAE技術。這是怎麼會看起來像(注意的是,由於C++ 11,在函數模板默認模板參數被允許):

#include <type_traits> 
#include <cstdint> 

template<class T, typename std::enable_if< 
    std::is_integral<T>::value>::type* = nullptr> 
int64_t to_int64t(const T& t) 
{ 
    return t; 
} 

template<class T, typename std::enable_if< 
    !std::is_integral<T>::value>::type* = nullptr> 
int64_t to_int64t(const T& t) 
{ 
    return t.to_int64t(); 
} 

int main() 
{ 
    int64_t i = 64; 
    auto x = to_int64t(i); 
} 

另一種可能性,但更詳細的,是定義輔助類模板(其可以部分專用)在detail命名空間和提供全球貨運 - 我不會用這種技術用於該用途的情況下,但我展示它,因爲它可能會來方便相關設計情況:

#include <type_traits> 
#include <cstdint> 

namespace detail 
{ 
    template<class T, bool = std::is_integral<T>::value> 
    struct helper { }; 

    template<class T> 
    struct helper<T, true> 
    { 
     static int64_t to_int64t(const T& t) 
     { 
      return t; 
     } 
    }; 

    template<class T> 
    struct helper<T, false> 
    { 
     static int64_t to_int64t(const T& t) 
     { 
      return t.to_int64t(); 
     } 
    }; 
} 

template<class T> 
int64_t to_int64t(const T& t) 
{ 
    return detail::helper<T>::to_int64t(t); 
} 

int main() 
{ 
    int64_t i = 64; 
    auto x = to_int64t(i); 
} 
+0

+1 t Ÿ - 我會試試這個 – kfmfe04 2013-03-24 13:24:44

+0

哦,我的,這是美麗的。 :) – 0x499602D2 2013-03-24 13:27:58

+0

@PeteBecker:感謝您的編輯:) – 2013-03-24 13:33:41

5

你可以用std::enable_if

template<class T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0> 
int64_t to_int64t(const T& t) 
{ 
     return t; 
} 

template<class T, typename std::enable_if<!std::is_integral<T>::value, int>::type = 0> 
int64_t to_int64t(const T& t) 
{ 
     return t.to_int64t(); 
} 
相關問題