libc++: Should std::istringstream's move ctr be nothrow?

When building and running the test:

std/input.output/string.streams/stringstream.cons/move2.pass.cpp

with MSVC I found the test was asserting. The crux of the issue is that a vector resize isn’t preserving the contents of the vector. Specifically:

We have a std::vectorstd::istringstream vecis. The test pushes a default constructed istringstream into the vector. It then modifies that element in place using the back() member of vector and then by calling the str() member of istringstream. Things go wrong when the next push_back happens. This causes the vector to resize and thus reallocate.

We eventually end up down the callstack in the __construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2) member of std::allocator_traits. This calls move_if_noexcept with template parameter std::istringstream&.

The problem is that this template uses type traits to determine whether to actualy move or just return a reference. The offending line is:

!is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value,

with _Tp = std::istringstream.

The declaration of std::istringstream doesn’t mark it’s move ctr as _NOEXCEPT so is_nothrow_move_constructible is false. This causes the contents of the vector to be lost as std::istringstream isn’t copy constructable (N.B. There’s another issue here as MSVC then picks the default ctr basic_istringstream(ios_base::openmode __wch) to do the “copy construct”. I believe the build should fail. But this is for another time).

So my question is, should std::istringstream’s move ctr be marked _NOEXCEPT? I’m not sure why this issue doesn’t occur with Clang. Thoughts welcomed. Is this some deficiency in MSVC? Is this a potential bug and Clang is smart enough to determine std::istringstream is noexcept? Have I missed a trick? :slight_smile:

It’s likely you can ignore the part about:

(N.B. There’s another issue here as MSVC then picks the default ctr basic_istringstream(ios_base::openmode __wch) to do the “copy construct”. I believe the build should fail. But this is for another time)

I had an earlier change which was still hanging around.