2

我们过度使用模板,我们不能总是告诉手头类型的签名,所以我们需要技术来隐藏最终将被优化的警告。我有一个简单的ASSERT(condition)宏,如果条件不为真,它会抛出一些东西。

目标是检查T键入count值的范围。我们需要它至少为零,最多为 的最大值size_t

template<typename SomeIntegral>
SomeIntegral ZERO()
{
    return SomeIntegral(0);
}

template<typename T>
class C
{
public:
  void f(T count)
  {
    std::vector<std::string> ret;
    ASSERT(count>=ZERO<T>()); // Check #1
    ASSERT(count<std::numeric_limits<size_t>::max()); // Check #2
    ret.reserve(size_t(count)); // Needs check #1 and #2 to succeed.
    // ...
  }
  // ...
};

#1 检查编译时没有警告,但 #2 检查说comparison between signed and unsigned integer expressions,因为在这种特殊情况下,计数具有带符号的类型。如果我能ASSERT((unsigned T) count < std::numeric_limits<size_t>::max())以某种方式说或类似的话……在这种情况下转换为无符号 T 是安全的,因为我们从检查 #1 中知道它至少为零。

...或者我可以使用其他与编译器无关的方法吗?

4

2 回答 2

7

我认为您可以使用std::make_signedor std::make_unsigned。哪个适合需要。


这是一个自定义实现。

namespace internal {

    #define MK_MAKESIGNED(T,V)             \
    template<> struct make_signed<T> {     \
      public:                              \
        typedef V type;                    \
    };                                     


    template<typename T>
    struct make_signed {
        typedef T type;
    };

    MK_MAKESIGNED(unsigned int, signed int);
    MK_MAKESIGNED(unsigned char, signed char);
    // .... can convert anything to anything.

    #undef MK_MAKESIGNED

};


internal::make_signed<unsigned char>::type c;
于 2013-05-09T12:20:08.853 回答
1

在第二个断言中同时应用于static_cast<unsigned long>左侧和右侧表达式:

ASSERT(static_cast<unsigned long>(count)
        < static_cast<unsigned long>(std::numeric_limits<size_t>::max()));

(我认为您的计数是整数,而不是浮点数 - 如果我错了,请选择最大的浮点数)。

于 2013-05-09T12:19:08.473 回答