Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to predicate on something having a signed numeric type?

Suppose I have some templated code which does the following:

T x = foo();
T y = -x;

Now, if T is a non-numeric type (or which doesn't have the unary minus implemented), the compilation will simply fail. But if it's an unsigned int, unsigned short etc., it will succeed, with a warning. So I would like to be able to do

T x = foo();
if (/* magic condition */ {
    T y = -x;
}

Can I write express the condition - which is checked either at compile time or at run time - of T's type being some signed numeric type? e.g. using typeid?

Note:

  • An assertion would also be nice, but I'd like something more flexible.
like image 372
einpoklum Avatar asked Dec 26 '22 17:12

einpoklum


2 Answers

C++11 has the is_unsigned trait, which you can use in a static_assert:

#include <type_traits>

template <typename T>
void foo()
{
    static_assert(std::is_unsigned<T>::value);

    T x = /* ... */
    T y = -x;

    /* ... */
}

If you need the check to be more dynamic, then just stick it in an if condition:

template <typename T>
void foo()
{
    if (!std::is_unsigned<T>::value) {
        /* To arrive here and for the following
           not to error out, we must have a numeric
           type that's not unsigned! */

        T x = /* ... */
        T y = -x;
    }
    else {
       /* Do something else for unsigned numeric
          types */
    }
}

More complex solutions involve overloads, std::enable_if and all sorts of other template metahackery, but the above may be all you need.

like image 176
Lightness Races in Orbit Avatar answered Dec 28 '22 05:12

Lightness Races in Orbit


Yes you can.

static_assert(std::is_unsigned<T>::value, "Not unsigned!");  

(You need to include type_traits for this to work.)

You can then naturally adjust your compilation process, potentially even with enable_if if you're sure there is no other way :).

like image 21
ScarletAmaranth Avatar answered Dec 28 '22 06:12

ScarletAmaranth