[英]Partial template specialization based on “signed-ness” of integer type?
鉴于:
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
当T
为unsigned
类型时,是否有任何聪明的方法不进行比较n >= 0
? 我尝试添加部分模板专门化:
template<typename T>
inline bool f( unsigned T n ) {
return n <= 100;
}
但是gcc 4.2.1不喜欢那样。 (我不认为这种模板偏特的将是法律反正。)
您可以将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,则可以在std
或std::tr1
命名空间中找到enable_if
和is_unsigned
。 否则,Boost具有类型特征库Boost.TypeTraits的实现 。 enable_if
的boost实现有些不同。 boost::enable_if_c
与TR1和C ++ 0x enable_if
相似。
您可以利用无符号整数的环绕行为。
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;
}
从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;
}
当T为无符号类型时,是否有任何聪明的方法不进行比较n> = 0? 我尝试添加部分模板专门化:
由于优化程序检测到条件,因此应删除该代码以进行比较。
对于Clang,添加-Wno-tautological-compare
来-Wno-tautological-compare
警告。 对于GCC / G ++,添加-Wno-type-limits
来-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
另请参见由于范围有限,比较总是错误的……
您可以为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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.