Notinlist
Notinlist

Reputation: 16640

C++: Conversion from T to unsigned T

We excessively use templates and we cannot always tell the signedness of a type at hand, so we need techniques to hide warnings that will be eventually optimized out. I have a simple ASSERT(condition) macro which throws something if the condition not evalutes to true.

The goal is to check the range of a T typed count value. We need it to be at least zero, at most the max of 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.
    // ...
  }
  // ...
};

The #1 check compiles without warning, but the #2 check says comparison between signed and unsigned integer expressions, because in this particular case the count has a signed type. If I could say ASSERT((unsigned T) count < std::numeric_limits<size_t>::max()) or similar somehow... Converting to unsigned T is safe in this situation, because we know from check #1 that it is at least zero.

... or what other compiler agnostic approach can I use?

Upvotes: 3

Views: 1874

Answers (2)

stardust
stardust

Reputation: 5988

I think you can use std::make_signed or std::make_unsigned. Whichever fits the need.


Here is a custom implementation.

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;

Upvotes: 9

Yulia V
Yulia V

Reputation: 3559

Apply static_cast<unsigned long> to both left hand and right hand side expressions in your second assert:

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

(I presume that your count is integer, not float - if I am wrong, go for a largest float type).

Upvotes: 1

Related Questions