Skip to main content
gamedev.net
🔒 Locked

C++ generating warning/error with unsigned math

Started by zedz 6 replies 1.2k views
Original Post
zedz
zedz
with msvc is it possible to generate an error if code trys to do math with an unsigned number eg uint32 a=0; a+=X; // error ( notw - of course I could make my own type + override the operators but thats obviously messy ) ta zed
gekko
gekko
You won't be able to overload with built-in types. There is a pragma to cause a specific warning to become an error. You might be able to do it for the sign/unsigned mismatch warning.

Look for something like:
#pragma warning(push)
#pragma warning(error: XXXXX)
// Your math code here
#pragma warning(pop)
-- gekko
Winegums
Winegums
I took a look to see if I could find a setting...but for some reason I can't even get it to throw up a warning with signed/unsigned pairings..
zedz
zedz
perhaps u have this in your code somewhere

#pragma warning (disable : 4018) // warning C4018: '==' : signed/unsigned mismatch
phresnel
phresnel
Quote:
Original post by zedz
with msvc
is it possible to generate an error if code trys to do math with an unsigned number

eg

uint32 a=0;

a+=X; // error

( notw - of course I could make my own type + override the operators but thats obviously messy )

ta zed


If you define your own type, you don't have to override operators. In fact, when you write your own type, you have to define those operators explicitly.

To forbid unsigned math, two solutions come to mind:

template
template <typename T> class restricted {public:        operator T () const {                return data;        }        restricted (T const &data_) : data (data_) {}        restricted(restricted const &r) : data (r.data) {}private:        restricted();        restricted & operator = (restricted const &);        T data;};int main () {        restricted<unsigned int> a = 5; // okay        unsigned int X = a;             // okay        a += X;                         // die        typedef restricted<unsigned int> cuint_t;        cuint_t c = 5; // okay        cuint_t d = c; // okay        c += c;        // die}


You can then cherry pick which operators you want to allow or forbid.

Or, if you just want to forbid anything but initialization, make it const:

const
int main () {        typedef const unsigned int cuint;        cuint a = 5;        cuint b = a;        a += b;}
NotAYakk
NotAYakk
I'd be more tempted with the following changes:
        // remove operator T, add:        T get() const {                return data;        }


To avoid:
restricted<unsigned int> foo;int x += foo; // works under old version


This is also possibly tempting, but probably not needed:
        // no implicit conversion from T: (you may not want this!)        explicit restricted (T const &data_) : data (data_) {}[...]// function to convert an expression to T:template<typename T>restricted<T> restrict( T const& data ) { return restricted<T>(data); }

the pair of which may be useful, or may just get in the way.

Finally, these are rather useful:
        // allow explicit conversion from sufficiently similar types:        // explicit is optional.        template<typename U>        explicit restricted (U const &data_) : data (data_) {}        // allow explicit conversion from another restricted type that is        // sufficiently related: (should probably stay explicit)        template<typename U>        explicit restricted (restricted<U> const& src) : data( src.get() ) {}

which, I'll admit, the operator T in the original, together with an implicit construction from T, would make not-useful in the prior implementation.

Basically you can have lots of control over your custom data type. You get compiler errors when someone tries to do something you don't allow.

You do have to be careful about implicit conversion of types. When you are making a restricted type, making these conversions explicit and manual can avoid the compiler 'working around your restrictions' possibly in ways you did not intend...
gekko
gekko
If you made your own type, you could use a templated operator + and type traits to solve the problem.

template <typename T>const MyType operator + (const T &rhs) const{    static_assert( std::tr1::is_signed<T>, "Unsigned numbers not allowed."  );    return data + rhs;}


You would need TR1 support for type traits (VS2008 SP1 has it, or Boost, or compiler intrinsics), and a static_assert (C++0x or build your own). But you will generate error messages this way.

Just an idea.
-- gekko
zedz
zedz
>> If you define your own type, you don't have to override operators. In fact, when you write your own type, you have to define those operators explicitly.

you are of course correct

>> Or, if you just want to forbid anything but initialization, make it const:

that would be sweet unfortunately I also want to be able to assign a number to it

thanks guys, looks like the only way is for me to create my own type


Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.