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

发布于 2024-10-13 10:45:52 字数 540 浏览 5 评论 0原文

给定:

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 时不进行比较 n >= 0无符号类型?我尝试添加部分模板专业化:

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

但 gcc 4.2.1 不喜欢这样。 (无论如何,我认为这种部分模板专业化是不合法的。)

Given:

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

When used with an unsigned type generates a warning:

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

Is there any clever way not to do the comparison n >= 0 when T is an unsigned type? I tried adding a partial template specialization:

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

but gcc 4.2.1 doesn't like that. (I didn't think that kind of partial template specialization would be legal anyway.)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

浅忆 2024-10-20 10:45:52

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

您可以在 std 中找到 enable_ifis_unsignedstd::tr1 命名空间(如果您的编译器分别支持 C++0x 或 TR1)。否则,Boost 有一个类型特征库的实现, Boost.TypeTraitsenable_if 的 boost 实现有点不同; boost::enable_if_c 与 TR1 和 C++0x enable_if 类似。

You can use enable_if with the is_unsigned type trait:

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;  
}

You can find enable_if and is_unsigned in the std or std::tr1 namespaces if your compiler supports C++0x or TR1, respectively. Otherwise, Boost has an implementation of the type traits library, Boost.TypeTraits. The boost implementation of enable_if is a little different; boost::enable_if_c is similar to the TR1 and C++0x enable_if.

吃颗糖壮壮胆 2024-10-20 10:45:52

您可以利用无符号整数的环绕行为。

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;
}   

You can take advantage of the wrap-around behavior of unsigned integers.

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)>());
}   

It's important not to say >= 0, to avoid a warning again. The following appears to trick GCC too

template<typename T>
inline bool f( T n ) {
  return (n == 0 || n > 0) && n <= 100;
}   
十年不长 2024-10-20 10:45:52

if constexpr您甚至不需要为此提供专业知识。与普通的 if 语句不同,如果表达式不为 true,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;
}   

Starting in with the introduction of if constexpr you don't even need to provide specializations for this. Unlike a normal if statement the code in the if constexpr will be discarded (not compiled) if the expression is not true. That means you can rewrite your function like

template<typename T>
inline bool f( T n ) 
{
    if constexpr (std::is_unsigned_v<T>)
        return n <= 100;
    else
        return n >= 0 && n <= 100;
}   
朮生 2024-10-20 10:45:52

当 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

另请参阅比较始终由于范围有限,错误...

Is there any clever way not to do the comparison n >= 0 when T is an unsigned type? I tried adding a partial template specialization:

The optimizer should drop the code for the compare since it detected the condition.

For Clang, add -Wno-tautological-compare to squash the warning. For GCC/G++, add -Wno-type-limits to squash the warning.

If you are using a compiler that support pragma diagnostic {push|pop} you can:

#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

Also see Comparison is always false due to limited range…

梦在深巷 2024-10-20 10:45:52

您可以为 unsigned 类型实现特殊的模板函数实现,例如:

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

UPDATE Unsigned flag

您可以为您想要使用的所有无符号类型实现不同的实现,或添加 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;

You can implement a special template function implementation for unsigned type like:

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

UPDATE Unsigned flag

You can implement different implementations for all unsigned types you'd like to use or add a bool flag like:

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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文