Update: I submitted this problem to the Microsoft Connect and the Feedback ID is 323765
I believe I found a bug in Visual C++ implementation of the C++ Standard Library (AFAIR, it’s provided by Dinkumware,Ltd.). This is my first trove of that kind in Visual C++, thus I should exclaim Hurray! ;-). The C++ library discussed here is shipped with Visual C++ 8.0 compiler from the Visual Studio 2005 Professional.
Shortly, in the std::basic_istream class, implementation of input operator overloaded for unsigned long with Microsoft specific modifier __w64 consists of incorrect cast from reference to non-const to unsigned long, a nonreference type - rvalue.
Here is the buggy implementation copied (stripping unimportant lines) from the <istream> header, by default installed in c:\program files\microsoft visual studio 8\vc\include\istream, near lines 309-326:
_Myt& operator>>(unsigned long __w64& _Val)
{ // extract an unsigned long
ios_base::iostate _State = ios_base::goodbit;
const sentry _Ok(*this);
if (_Ok)
{ // state okay, use facet to extract
const _Nget& _Nget_fac = _USE(ios_base::getloc(), _Nget);
_Nget_fac.get(_Iter(_Myios::rdbuf()), _Iter(0),
*this, _State, (unsigned long)_Val);
}
_Myios::setstate(_State);
return (*this);
}
In the code above, bug is in the line where std::num_get::get function is called. The 5th parameter is casted from reference to nonreference type:
(unsigned long)_Val
and, from the C++ Language Standard/3.10:
6 An expression wich holds a temporary object resulting from a cast to a nonreference type is an rvalue.
Next, the _std::numget::get function call tries to bind the rvalue to reference to non-const type, according to its prototype:
// C++ Standard/22.2.2.1 - std::num_get class members
_InIt get(_InIt _First, _InIt _Last,
ios_base& _Iosbase, ios_base::iostate& _State,
unsigned long& _Val)
However, the C++ Standard/8.5.3 defines that
the reference shall be to a non-volatile const type.
Solution
The simplest solution is to fix the invalid cast, so the buggy line:
_Nget_fac.get(_Iter(_Myios::rdbuf()), _Iter(0),
*this, _State, (unsigned long)_Val);
reads
_Nget_fac.get(_Iter(_Myios::rdbuf()), _Iter(0),
*this, _State, (unsigned long&)_Val);
alternatively, it’s also possible to completely remove the cast of _Val object.
By the way, if you want to keep your C++ programs portable, it’s a good idea to disable Visual C++ language extensions using compiler option /Za.