2011-01-21 58 views
18

考慮:基於整數類型「有符號」的部分模板專門化?

template<typename T> 
inline bool f(T n) { 
    return n >= 0 && n <= 100; 
} 

當與unsigned型用於生成一個警告:

unsigned n; 
f(n); // warning: comparison n >= 0 is always true 

有沒有什麼聰明的辦法不是做比較n >= 0Tunsigned類型?我嘗試添加部分模板專業化:

template<typename T> 
inline bool f(unsigned T n) { 
    return n <= 100; 
} 

但gcc 4.2.1不喜歡那樣。 (我並不認爲類型的部分模板專業化將是合法的。)

+2

注有函數模板,只有充分專業化無偏特。也就是說,對於函數模板來說,完全專業化通常是一個壞主意,因爲關於什麼是專門化的,什麼是重載的,以及重載決策如何決定使用什麼是複雜和複雜的。值得慶幸的是,重載和SFINAE(替換失敗不是錯誤)在這裏就足夠了。 – 2011-01-21 18:12:53

+0

對此,我從Clang 3.8(或GCC 8.0)沒有收到警告。如果我刪除`f`上的模板,我可以理解。是否有考慮模板實例化的`-Wtautological-compare`版本? – user2023370 2018-02-01 17:42:57

回答

22

您可以使用enable_ifis_unsigned型特點:

template <typename T> 
typename std::enable_if<std::is_unsigned<T>::value, bool>::type f(T n) 
{ 
    return n <= 100; 
} 

template <typename T> 
typename std::enable_if<!std::is_unsigned<T>::value, bool>::type f(T n) 
{ 
    return n >= 0 && n <= 100; 
} 

您可以找到stdstd::tr1命名空間enable_ifis_unsigned如果你的編譯器支持分別C++ 0x或TR1。否則,Boost有一個類型特徵庫的實現,Boost.TypeTraitsenable_if的推動實施有點不同; boost::enable_if_c類似於TR1和C++ 0x enable_if

14

您可以利用無符號整數的環繞行爲。

template<bool> struct bool_ { }; 

template<typename T> 
inline bool f(T n, bool_<false>) { 
    return n >= 0 && n <= 100; 
} 

template<typename T> 
inline bool f(T n, bool_<true>) { 
    return n <= 100; 
} 

template<typename T> 
inline bool f(T n) { 
    return f(n, bool_<(static_cast<T>(-1) > 0)>()); 
} 

重要的是不要說>= 0,以避免再次發出警告。下面出現欺騙GCC太

template<typename T> 
inline bool f(T n) { 
    return (n == 0 || n > 0) && n <= 100; 
} 
+0

+1最後一個技巧 – TonyK 2011-01-21 19:02:57

0

您可以實現一個特殊的模板功能實現爲unsigned類型,如:

template<class T> bool f(T val); 
template<> bool f<unsigned>(unsigned val); 

UPDATE無符號標誌

您可以實現對所有不同的實現無符號類型您想使用或添加bool國旗像:

template <class T, bool U> bool f(T val) 
{ 
     if (U) 
       return val <= 100; 
     else 
       return (val >=0) && (val <= 100); 
} 

... 

cout << f<int, false>(1) << endl; 
cout << f<int, false>(-1) << endl; 
cout << f<char, true>(10) << endl; 
1

當T是一個無符號類型時,是否有任何巧妙的方式不進行比較n> = 0?我嘗試添加部分模板特化:

優化程序應該放棄比較的代碼,因爲它檢測到條件。

對於Clang,添加-Wno-tautological-compare以壓扁警告。對於GCC/G ++,添加-Wno-type-limits以壓扁警告。

如果您使用的是支持pragma diagnostic {push|pop}你可以編譯:

#if (GCC_VERSION >= 40600) || (LLVM_CLANG_VERSION >= 10700) || (APPLE_CLANG_VERSION >= 20000) 
# define GCC_DIAGNOSTIC_AVAILABLE 1 
#endif  

#if MSC_VERSION 
# pragma warning(push) 
# pragma warning(disable: 4389) 
#endif 

#if GCC_DIAGNOSTIC_AVAILABLE 
# pragma GCC diagnostic push 
# pragma GCC diagnostic ignored "-Wsign-compare" 
# if (LLVM_CLANG_VERSION >= 20800) || (APPLE_CLANG_VERSION >= 30000) 
# pragma GCC diagnostic ignored "-Wtautological-compare" 
# elif (GCC_VERSION >= 40300) 
# pragma GCC diagnostic ignored "-Wtype-limits" 
# endif 
#endif 

template<typename T> 
inline bool f(T n) { 
    return n >= 0 && n <= 100; 
} 

#if GCC_DIAGNOSTIC_AVAILABLE 
# pragma GCC diagnostic pop 
#endif 

#if MSC_VERSION 
# pragma warning(pop) 
#endif 

另見Comparison is always false due to limited range…