Reputation:
I ran into this problem when I was doing the following code:
int average = std::accumulate(vi.begin(), vi.end(), 0) / vi.size();
Without an int
cast on vi.size()
the output is garbage, because size()
returns an unsigned integer.
I never would've figured this out if I hadn't googled a reference for vector. Is there a way of avoiding this trap? With -Wall
and -pedantic
, gcc doesn't seem to give any warnings about this kind of division.
Upvotes: 3
Views: 2590
Reputation: 158469
gcc
has the -Wconversion
flag, which for this case warns me:
warning: conversion to ‘int’ from ‘std::vector<int>::size_type {aka long unsigned int}’ may alter its value [-Wconversion]
int average = std::accumulate(vi.begin(), vi.end(), 0) / vi.size();
^
The gcc docs says:
-Wconversion
Warn for implicit conversions that may alter a value. This includes conversions between real and integer, like abs (x) when x is double; conversions between signed and unsigned, like unsigned ui = -1; and conversions to smaller types, like sqrtf (M_PI). Do not warn for explicit casts like abs ((int) x) and ui = (unsigned) -1, or if the value is not changed by the conversion like in abs (2.0). Warnings about conversions between signed and unsigned integers can be disabled by using -Wno-sign-conversion.
For C++, also warn for confusing overload resolution for user-defined conversions; and conversions that never use a type conversion operator: conversions to void, the same type, a base class or a reference to them. Warnings about conversions between signed and unsigned integers are disabled by default in C++ unless -Wsign-conversion is explicitly enabled.
Upvotes: 5