Re: What is the correct behaviour?
Jiang wrote:
James Kanze wrote:
Jonne Lehtinen wrote:
Hello, I just stumbled upon two different behaviours with two
different compilers. Here's a sample code....
std::string a( "-432" );
unsigned long b = 0;
std::stringstream stream;
if( !(stream << a && stream >> b) ) {
// Should fail?
}
On g++ 4.1.2 (20061026 (Debian "prerelease")) and g++ 3.4.2 it
does indeed fail but on my school's modified g++ 4.1 (uses
stlport 5.0.1) and on Visual C++ 2005 it doesn't fail. Which
behaviour is correct?
It's undefined behavior, but from a quality of implementation
point of view
IMHO, this is implementation-defined behavior.
In 4.7(Integral conversions), the standard says:
If the destination type is signed, the value is unchanged if it
can be represented in the destination type (and bit-field width);
otherwise, the value is implementation-defined.
There's no integral conversion involved. Integral conversions
are between integral types, and do not use the standard library.
The istream's extractors uses num_get, which handling
numeric formatting and conversion.
I know. And they define the semantics by reference to fscanf in
the C standard. And the C standard says that if the converted
value isn't representable in the target type, the behavior is
undefined.
As it happens, however, the C standard defines the semantics of
the conversion "as if" strtoul was used. And strtoul defines a
conversion of "-432" to unsigned long; the results must be equal
to ULONG_MAX+1-432. I'd missed this little detail before, but
it would seem that if we take the standard literally, the
conversion is well defined, with well defined results, and an
implementation which reports an error is not conformant.
I don't know for sure whether this is intentional or simply an
accidental result of applying the general principle used to
define signed conversions to unsigned conversions. At any rate,
I'm not yet to the point of posting a bug report to g++ because
they generate an error.
, I would expect failure. You have the value -432,
which isn't representable in an unsigned long.
Indeed the conversion should fail in my mind.
I test the above code using Boost::lexical_cast, it does
report the fail by throwing bad_lexical_cast exception:
I suspect that boost::lexical_cast doesn't do anything special,
but simply reacts to errors detected in the stringstream it
uses. So whether you get bad_lexical_cast will depend on the
compiler: of the four libraries I have access to, two generate
an error, and two don't (but one that doesn't misses a lot of
other errors as well).
#include <boost/lexical_cast.hpp>
#include <iostream>
int main()
{
using boost::lexical_cast;
using boost::bad_lexical_cast;
try {
std::string str("-232");
unsigned long i = lexical_cast<unsigned long>(str);
}
catch(bad_lexical_cast& e) {
std::cout << e.what() << std::endl;;
}
}
$ ./blc
bad lexical cast: source type value could not be interpreted as target
For which compiler? Which standard library?
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]