return str;is guaranteed to move, not copy, out of str if (as unlikely as it is) it cannot apply copy elision.
|the return statement is a call to the move constructor if there is one.|
Copy elision is the only allowed form of optimization that can change the observable side-effects. Because some compilers do not perform copy elision in every situation where it is allowed (e.g., in debug mode), programs that rely on the side-effects of copy/move constructors and destructors are not portable.
Types without a move constructor, but with a copy constructor that accepts const T& arguments, satisfy std::is_move_constructible.
Move constructors are usually noexcept, since otherwise they are unusable in any code that provides strong exception guarantee.
In many implementations, is_nothrow_move_constructible also checks if the destructor throws because it is effectively noexept(T(arg)). Same applies to is_trivially_move_constructible, which, in these implementations, also requires that the destructor is trivial: GCC bug 51452 LWG issue 2116.
noexcept. Maybe this was fixed in gcc4.7 ?
std::is_move_constructiblebefore the return statement to maybe provide a clue as to what is really happening there? Edit: Maybe this was a problem then, but not now: ctor & dtor are supposed to always be noexcept to provide the strong guarantee