Implementation bug?

I just noticed this weird behavior from MSVC:
1
2
3
4
5
std::string s = "-1";
std::stringstream stream(s);
unsigned n;
assert(!!(stream >> n)));
assert(n == std::numeric_limits<unsigned>::max());
I believe GCC was doing it too. Clang was the only one that behaved as I would have expected (making the conversion fail).
Is this relevant?
http://en.cppreference.com/w/cpp/locale/num_get/get

From the "notes" section:
The result of converting a negative number string into an unsigned integer was specified to produce zero until C++17, although some implementations followed the protocol of std::strtoull which negates in the target type, giving LLONG_MAX for "-1", and so produce the largest value of the target type instead. As of C++17, strictly following std::strtoull is the correct behavior.


Then:
http://en.cppreference.com/w/cpp/string/byte/strtoul
If the minus sign was part of the input sequence, the numeric value calculated from the sequence of digits is negated as if by unary minus in the result type, which applies unsigned integer wraparound rules.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <limits>
#include <cassert>
using namespace std;

int main()
{
   string s = "-1";
   stringstream stream(s);
   unsigned n;
   stream >> n;
   cout << "n=" << n << "    Failbit is " << boolalpha << stream.fail() << endl;
   cout << "max usigned is " << numeric_limits<unsigned>::max() << endl;

// assert(!!(stream >> n));
// assert(n == std::numeric_limits<unsigned>::max());

   unsigned N = -1;
   cout << "Result of assigning -1 to an unsigned int is " << N << endl;
}


n=4294967295    Failbit is false
max usigned is 4294967295
Result of assigning -1 to an unsigned int is 4294967295

gcc version 6.3.0 (MinGW.org GCC-6.3.0-1)
Last edited on
What's the deal with Clang, then?
Seems to be a bit murky. If I'm reading the cpp-reference right then Clang is doing what it was supposed to do pre-c++17 and not doing what it's supposed to do post c++17! But I haven't got a copy of Clang and I could well be misinterpreting cpp-reference.
Well, no. It clearly says that pre-C++17 n should be zero. But Clang is not setting n to zero (or maybe it is, I didn't check), it's making the conversion fail.
I ran my test program on Clang 3.8.0 on rextester.com. It set n to 0 AND set the failbit to true (i.e. screwed the stream). Direct assignment to N gives largest unsigned as before.

So I don't think Clang is working as per the standard either side of C++11.

But feeding a negative number into an unsigned int isn't something I do by choice!
Registered users can post here. Sign in or register to post.