Justification for std :: move_if_noexcept still moving throwing types just for moving?

move_if_noexcept will be:

  • return rvalue - ease of movement - if the move constructor is noexcept or if there is no copy constructor (type only for move)
  • returns lvalue - force copy - otherwise

I found this rather unexpected, since the type of movement with throwing movement-ctor only will still have this move-ctor called by code that uses move_if_noexcept .

Was there a reasonable justification for this? (Maybe right or between the lines of N2983 ?)

Wouldn’t it be better to not compile the code than to run into the irreversible movement script? The vector example given in N2983 is good:

 void reserve(size_type n) { ... ... new ((void*)(new_begin + i)) value_type( std::move_if_noexcept( (*this)[i]) ) ); } catch(...) { while (i > 0) // clean up new elements (new_begin + --i)->~value_type(); this->deallocate( new_begin ); // release storage throw; } *!* // -------- irreversible mutation starts here ----------- this->deallocate( this->begin_ ); this->begin_ = new_begin; ... ... 

The comment indicated in the marked line is actually erroneous - for move-only types that can throw on the move construct, it is possible that the unsuccessful - irreversible mutation really begins when we move the old elements to their new positions.

Looking briefly at it, I would say that throwing only the type of motion cannot be inserted into the vector otherwise, but maybe it should not?

+7
c ++ move-semantics noexcept
source share
1 answer

Looking briefly at this, I would say that the propelling type of movement could not be placed in the vector otherwise, but perhaps it should not be?

I believe that you well summarized the choices the committee had for move-only-noexcept (false) type containers.

  • Allow them, but with basic security exceptions, not strong for some operations.
  • Deny them at compile time.

but. The committee absolutely felt that they could not easily change the existing C ++ 03 code, with strong exceptional security, ensuring the safety of the main exceptions.

C. For those functions that have strong protection against exclusion, the committee preferred that these members still have strong exception safety, even for code that could not yet be written (for example, functions that control types only for movement).

The committee understood that it could fulfill both of the above goals, except in the case described in B), where the type of movement can be thrown during the movement. These cases are limited to several vector IIRC member functions: push_back , reserve . Please note that other vector members already offer only basic exception safety (even in C ++ 98/03), for example: assignment, insertion (if not inserted at the end), erase.

With all this in mind, the committee made a decision that the client should create a vector type move-only-noexcept (false), it would be more useful for the client to get rid of the strong security of exceptions to the basic one (as is already done for other elements of the vector), and not to refuse compilation.

This will only be the new code that the client writes for C ++ 11, and not for obsolete code, since move types do not exist before C ++ 11. And, no doubt, C ++ 11 teachers should encourage their students to write noexcept ( true) participants in the movement. However, code with a basic exception security guarantee is not so dangerous and unusual that it should be prohibited. After all, std :: lib is already populated with code containing only the basic exception security guarantee.

+6
source share

All Articles