I’m creating a primitive type wrapper, which can use boost::lexical_cast for setting its value from a string. It works fine, but for some reason std::istream extraction operator sets the failbit. The following program prints:
123.45
EXCEPTION: ios_base::failbit set
But if you comment out the line “inStream.exceptions( …” it works and prints:
123.45
123.45
It doesn’t make a difference if you compile with unicode or not, or if you use int or float as ValueType, the failbit gets set in any case.
#include <conio.h>
#include <exception>
#include <iostream>
#include <string>
#include <tchar.h>
#include <boost/lexical_cast.hpp>
#if defined(UNICODE) || defined(_UNICODE)
typedef std::wstring StringType;
typedef std::wistream IStreamType;
#else
typedef std::string StringType;
typedef std::istream IStreamType;
#endif
#if 1 // Use float
typedef float ValueType;
#define VALUE_STRING _T("123.45")
#else // Use int
typedef int ValueType;
#define VALUE_STRING _T("123")
#endif
struct Castable {
ValueType m_val;
};
inline IStreamType& operator>> ( IStreamType& inStream, Castable& castable )
{
inStream.exceptions( IStreamType::failbit | IStreamType::badbit );
inStream >> castable.m_val;
return inStream;
}
int _tmain(int argc, _TCHAR* argv[])
{
try{
StringType sVal = VALUE_STRING;
ValueType val;
val = boost::lexical_cast<ValueType>(sVal);
std::cout << val << std::endl;
Castable cst;
cst = boost::lexical_cast<Castable>(sVal);
std::cout << cst.m_val << std::endl;
}catch( std::exception& ex ){
std::cout << "EXCEPTION: " << ex.what() << std::endl;
}
_getch();
return 0;
}
Why would std::istream think something has gone wrong?
One reason for this might be that the implementation of
lexical_castmight deliberately try to cause some stream to fail in order to check that all of the input text was consumed. For example, a naive implementation might look like this:The idea here is that the final check tries to break the stream to see if something was left over. If you enable exceptions, this will turn something that should have been a normal stream failure detectable with
failbitinto an exception, which is something the code didn’t expect.More generally, though, you shouldn’t be setting stream settings inside of an extraction routine. That’s up to the caller to do. Otherwise, no matter what you try to do with your stream before calling the extraction routine, the routine will override your preferences. It would be bad, after all, if I explicitly disabled exceptions and then had exceptions happen anyway because you turned them back on inside
operator >>.Hope this helps!