I may be missing something but I think that the default istream::operator >>
is not able to detect base automatically from the input. The manipulator std::hex
can only be used to force the base to 16 but it will be applied to all input without regard for prefix "0x" or suffix "h".
We can work around by overloading operator >>
for a custom type and call std::stoi()
:
struct ParsedInt
{
int val;
};
inline std::istream& operator>>( std::istream& strm, ParsedInt& i )
{
std::string s; strm >> s;
i.val = 0;
if( ! s.empty() )
{
if( s.back() == 'h' )
// explicitly use base 16 to parse hex
i.val = static_cast<int>( std::stoul( s, nullptr, 16 ) );
else
// stoi() with base 0 will detect prefix "0x".
i.val = static_cast<int>( std::stoul( s, nullptr, 0 ) );
}
return strm;
}
Usage example:
int main()
{
std::stringstream ss( "11 0xb bh -11 0xffffffff fffffffeh" );
ParsedInt i;
while( ss >> i )
{
std::cout << i.val << "\n";
}
}
Output:
11
11
11
-11
-1
-2
Live Demo.
Edit:
Original code crashed with std::out_of_range
exceptions for negative hex numbers like 0xFFFFFFFF
, this has been fixed by replacing std::stoi()
with std::stoul()
and static_cast
ing the result to int
.