2013/2/21 Dmitry Marakasov <amd...@amdmi3.ru>: > Hi! > > I'm not really sure which (g++ or libstdc++) problem this really is, so > posting into both lists.
It doesn't look like a problem of libstdc++ to me (see below why). > The problem is described here: > http://cpp-next.com/archive/2009/10/exceptionally-moving/ > > - You have two classes: > A, which has a proper move constructor which doesn't throw > B, which which only has copy constructor which may throw > - You have an std::pair<A, B> > - You move a pair > std::pair<A, B> pair1; > try { > std::pair<A, B> pair2(std::move(a)); > } > > What happens: > - A part is moved with move constructor. This is obviously destructive > to pair1. > - B part is copied as it doesn't have move constuctor. > - Now, that copy constructor throws (which is pretty expectable is it > likely allocates resources). After this, as A part was already moved, > we're left with corrupted pair1 (with empty A part). I agree that this is the current to be expected behaviour. But it is what the standard currently requires: template <class T1, class T2> struct pair { [..] pair(const pair&) = default; pair(pair&&) = default; [..] }; > The same problem applies to most containers, but, for example, in > std::vector it is solved gracefully: > > --- bits/vector.tcc from gcc-4.8: > pointer __tmp = _M_allocate_and_copy(__n, > _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start), > > _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish)); > --- > > so move semantics are only used IF the type has non-throwing(noexcept) > move constructor. > > However, with pair this does not apply: > > --- bits/stl_pair.h from gcc-4.8: > struct pair { > ... > constexpr pair(pair&&) = default; > --- I agree with the divergence relative to containers, but the current specification imposes this requirement. User-code could observe any difference (you do, for example), therefore it is hard to change. I suggest that you instead send an LWG issue submission request as described here: http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#submit_issue > Either the default constructor generated by gcc is unsafe, or there > should be custom, safe move constuctor with corresponding enable_if. > > I lean towards the former, as safe default move constuctors should be > always generated probably, and specific ones may be really hard to > implement for more complex types (tuples). While I agree with your arguments this is primarily a standard Library specification problem. > I've written a small program which demonstrates the problem: > > https://gist.github.com/AMDmi3/5005557 > > tested it on FreeBSD with gcc-4.8 and on Debian with gcc-4.7, and it > showed problem on both. > > Is this really a gcc problem? Should I file a bug? I don't think so. I suggest to send an LWG issue request instead. - Daniel