2011-01-21 56 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…