Boost logo

Boost :

From: Oliver Kullmann (O.Kullmann_at_[hidden])
Date: 2005-10-17 07:10:32


Hello,

Consider the following basic task: Given an integer variable "n"

int n;

and an input stream "in"

std::istream in;

read an integer from in and put it into n. The "solution"

in >> n;

is not a solution, since according to 27.6.1.2.2 from the C++ standard
the locale's num_get<> object is invoked, which according to
22.2.2.1.2 from the C++ standard invokes scanf from the C library,
which then according to 7.19.6.2 from the C standard, clause 10,
yields undefined behaviour if the number represented in the stream is not
representable by the type int.

Thus, since "in" represents here user input, and user input shall never
yield undefined behaviour, we cannot use "in >> n;".

It seems that in the boost library there is no tool to remedy the
situation:

 - Although boost::lexical_cast does not specify which errors are checked
   and which are not, it seems that lexical_cast just forwards the action
   to some std::stringstream object, and the same problem as above
   arises.

 - Boost::numeric_cast only works with objects of numeric types, and
   thus does not contribute to the problem of converting a character
   sequence into an integer.

So, it seems, that this fundamental problem is neither addressed by
the C++ standard library nor by the Boost library, and thus I have to
write a parser etc. myself for the arithmetic types in C++ ?

Is this really so??

Oliver

P.S. The easiest way to parse the input from in and check for overflow
/ underflow seems to me to get the sequence of digits into a
std::string digits;
erase leading zeros, and compare this string to the string
std::string ref = boost::lexical_cast<std::string>(std::numerical_limits<int>::max());
In case of overflow: If digits.size() < ref.size(), then fine, if
digits.size() > ref.size(), then bad, otherwise we use lexicographical
comparison.

A convenient design then perhaps is a wrapper class

template <typename Int>
class safe_wrapper;

such that we can use

safe_wrapper<int> n;
in >> n;
if (not in)
  throw Error;


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk