繁体   English   中英

基于整数类型的“有符号性”的部分模板专业化?

[英]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

Tunsigned类型时,是否有任何聪明的方法不进行比较n >= 0 我尝试添加部分模板专门化:

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

但是gcc 4.2.1不喜欢那样。 (我不认为这种模板偏特的将是法律反正。)

您可以将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;  
}

如果编译器分别支持C ++ 0x或TR1,则可以在stdstd::tr1命名空间中找到enable_ifis_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;
}   

开始,引入了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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM