1
votes

So on a fairly regular bases it seems I find the type of some constant I declared (typically integer, but occasionally other things like strings) is not the ideal type in a context it is being used, requiring a cast or resulting in a compiler warning about the implicit cast.

E.g. in one piece of code I had something like the below, and got a signed/unsigned comparison issue.

static const int MAX_FOO = 16;

...

if (container.size() > MAX_FOO) {...}

I have been thinking of just always using the smallest / most basic type allowed for a given constant (e.g. char, unsigned char, const char* etc rather than say int, size_t and std::string), but was wondering if this is really a good idea, and if there are some places where it would potentially be a really bad idea? e.g. code using the 'auto' keyword (or perhaps templates) getting a too small type and overflowing on what appeared to be a safe operation?

1
Sizes are generally unsigned, that's why there is both the unsigned size_t and the signed ssize_t.Some programmer dude
For container sizes I use either auto or ContainerType::size_type as appropriate.Captain Obvlious

1 Answers

1
votes

Going for the smallest type that can hold the initial value is a bad habit. That invites overflow.

Always code for the most general (which according to Murphy's Law is the worst) case. As templates generalize things, that makes the worst case a lot worse. Be prepared for bizarre kinds of overflows and avoid negative numbers while unsigned types are in the neighborhood.

std::size_t is the best choice for the size or length of anything, for the reason you mentioned. But subtract pointers and you get a std::ptrdiff_t instead. Personally I recommend to cast the result of such a subtraction to std::size_t if it can be guaranteed to be positive.

char * does not own its string in the C++ sense as std::string does, so the latter is the more conservative choice.

This question is so broad that no more specific advice can be made…