C ++ 11 / VS2010: Returning containers of uncovered but movable objects

Consider the following code:

#include <vector> #include <boost/noncopyable.hpp> struct A : private boost::noncopyable { A(int num, const std::string& name) : num(num), name(name) { } A(A&& other) : num(other.num), name(std::move(other.name)) { } int num; std::string name; }; std::vector<A> getVec() { std::vector<A> vec; vec.emplace_back(A(3, "foo")); // vec.emplace_back(3, "foo"); not available yet in VS10? return vec; // error, copy ctor inaccessible } int main ( int argc, char* argv[] ) { // should call std::vector::vector(std::vector&& other) std::vector<A> vec = getVec(); return 0; } 

This does not compile under VS2010, because obviously A is noncopyable and therefore std::vector<A> cannot be copied. Accordingly, I cannot return std::vector<A> from a function.

However, it does not seem to me that this kind of thing cannot be considered with the concept of RVO. If Return Value Optimization has been applied here, the copy may be omitted and the call to getVec() will be valid.

So what would be the right way to do this? Is this even possible in VS2010 / C ++ 11?

+6
source share
2 answers

If return vec; not compiling, VS2010 does not yet support move semantics. Typically, automatic variables are moved implicitly if they are returned from a function. Use return std::move(vec); as a temporary workaround and take a note in your head to get rid of std::move in the future.

In this answer to frequently asked questions, a full description can be found under the heading "Moving from Functions".

In addition, your two-argument constructor creates a copy of the string argument, which is passed by a const-reference. I would suggest taking an argument by value and moving it to a member:

 A(int num, std::string name) : num(num), name(std::move(name)) { } 

Thus, you reduce the number of copies needed. See Need speed? Scroll by value for more information.

Also, since your move constructor does nothing special, you can default it:

 A(A&& other) = default; 

This makes it more reliable in the face of change. Errors are rarely hidden in code that you don't write :)

+11
source

However, it does not seem to me that this kind of thing cannot be considered with the concept of RVO.

Elision, a generic term for a type such as named return value optimization, is optimization. This is not required. The specification allows this, but does not force any implementation to be performed, even when it is allowed.

Thus, in order to ensure consistency between compilers that allow the exception and those that do not, if permission is allowed by the operation, the compiler must still verify that copying / moving will be eliminated possibly taking into account the current state of the code. Therefore, if the copy / move constructor is not available, the operation fails, even if the compiler does not actually name it.

In this case, Visual Studio 2010 seems to be confused in this regard. It recognizes that return vec; must be moving out of vec . However, it seems that for VS2010 std::vector implementation requires a move destination operator; without it, he will try to copy.

+6
source

Source: https://habr.com/ru/post/921107/


All Articles