假设:
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 >= 0
是T
类型时,是否有任何聪明的方法不进行比较unsigned
?我尝试添加部分模板专业化:
template<typename T>
inline bool f( unsigned T n ) {
return n <= 100;
}
但gcc 4.2.1不喜欢这样。 (我不认为 那种部分模板专业化无论如何都是合法的。)
答案 0 :(得分:24)
您可以将enable_if
与is_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;
}
如果编译器分别支持C ++ 0x或TR1,则可以在enable_if
或is_unsigned
命名空间中找到std
和std::tr1
。否则,Boost具有类型特征库Boost.TypeTraits的实现。 enable_if
的推动实施略有不同; boost::enable_if_c
类似于TR1和C ++ 0x enable_if
。
答案 1 :(得分:15)
您可以利用无符号整数的环绕行为。
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;
}
答案 2 :(得分:3)
从c++17开始,开始引入if constexpr
,您甚至不需要为此专门提供专业知识。与普通的if语句不同,如果表达式不为真,if constexpr
中的代码将被丢弃(不编译)。这意味着您可以像这样重写函数
template<typename T>
inline bool f( T n )
{
if constexpr (std::is_unsigned_v<T>)
return n <= 100;
else
return n >= 0 && n <= 100;
}
答案 3 :(得分:1)
当T是无符号类型时,有没有聪明的方法不进行比较n&gt; = 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
答案 4 :(得分:0)
您可以为unsigned
类型实现特殊的模板函数实现,如:
template<class T> bool f(T val);
template<> bool f<unsigned>(unsigned val);
更新无符号标记
您可以为要使用的所有无符号类型实现不同的实现,或添加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;