Talk:cpp/language/move assignment

So I'll start from beginning (: On this page there is possible implementation of std::remove algorithm, which works incorrectly with T = std::vector from libc++ and libstdc++. (works correctly with msvc)

Test, for prove:


 * 1) include // std::cout
 * 2) include
 * 3) include

namespace my {

template ForwardIt remove(   ForwardIt first,    ForwardIt last,    const T& value) { ForwardIt result = first; for (first != last; ++first) { if (!(*first == value)) { *result = std::move(*first); ++result; } }  return result; }

}

inline void fundamental_test { std::cout << "fundamental test:" << std::endl; const int val_to_remove = 4;

std::vector int_vec;

int_vec.push_back(1); int_vec.push_back(2); int_vec.push_back(3);

std::cout << "size = " << int_vec.size << std::endl;

int_vec.erase(     my::remove(int_vec.begin, int_vec.end, val_to_remove), // test      int_vec.end  );

std::cout << "size = " << int_vec.size << std::endl;

for(const auto& i: int_vec) { std::cout << i << std::endl; } }

inline void container_test { std::cout << "stl container test" << std::endl; typedef std::vector Element; typedef std::vector Container;

Element val_to_remove; val_to_remove.push_back(1); val_to_remove.push_back(2); val_to_remove.push_back(3); val_to_remove.push_back(4);

Element val_other; val_other.push_back(1); val_other.push_back(4); val_other.push_back(5);

Container container;

container.push_back(val_other); container.push_back(val_other); container.push_back(val_other);

container.erase(     my::remove(container.begin, container.end, val_to_remove), // test      container.end  );

std::cout << "size = " << container.size << std::endl; for (const auto& i: container) { if (i.empty) { std::cout << "empty"; }   else { for (const auto& j: i) { std::cout << j << " "; }   }    std::cout << std::endl; } }

int main { fundamental_test; container_test;

return EXIT_SUCCESS; } If you use std::remove from library: fundamental test: size = 3 size = 3 1 2  3  stl container test size = 3 1 4 5  1 4 5   1 4 5

but if you use my::remove: fundamental test: size = 3 size = 3 1 2  3  stl container test size = 3 empty empty empty

The problem is in line: *result = std::move(*first); when result is equal to first it self-move-assigning => cleared.

What I'm trying to say (: ? If you want to write algorithm that works with all implementation of stl, you need to remember that self-move-assign clear you container. And important notes about this implementaion, that implementation is correct and fit c++ standard.

Environment: g++ 4.7 ubuntu, macos clang 5.0, msvc 2012 Ruslo 13:55, 25 August 2013 (PDT)


 * Okay, I think I'm starting to understand. 17.6.4.9/1 of n3690 ("Function arguments") says "Each of the following applies to all arguments to functions defined in the C++ standard library...If a function argument binds to an rvalue reference parameter, the implementation may assume that this parameter is a unique reference to this argument."
 * So that basically means that containers like std::vector don't need to check for self-assignment in their operator=, because they can assume that they'll never encounter self assignment.
 * Does that sound right? If so, I wonder if this is something that would be useful to have on the various container operator= pages.  (Although it would be kind of repetitive, which is an argument for just saying it once e.g. here.) --Nate 18:28, 25 August 2013 (PDT)
 * I think any page you can refer to will be fine. But I can't image how to do it without std::move function (of course if you don't create your own). My point is, you just need to remember easy pattern: when you see 'x = std::move(y)' can you guarantee, that x is not y? Ruslo 20:56, 25 August 2013 (PDT)
 * This looks like the "possible implementation" of std that was posted on this wiki, which is simply invalid. I'll fix it. As for library self-moves, there aren't too many move assignment operators in the standard library, no harm mentioning in every container::operator= that self-move-assignment is not necessarily tested...  on second thought, there are plenty more resource-owning classes in the library. --Cubbi 02:59, 26 August 2013 (PDT)

Move assignment operator taking arguments passed by value??
In the Copy-and-Swap idiom section. You provide example like this:

T& T::operator=(T arg) {   swap(arg); return *this; }

This is hardly a move assignment operator; it's a copy assignment operator!
 * Nothing is copied if the argument is a movable rvalue. --Cubbi (talk) 16:07, 30 December 2015 (PST)