Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++03 moving a vector into a class member through constructor (move semantics)

I only have access to C++03 and I often want to move a vector into a function the way you can do it in C++11. The question how to do it not to confuse the user of the code too much. So my question is how did programmers do it before C++11.

I know that vector can be "moved" using swap function. So here is what I have come up with:

class Foo
{
public:
    Foo(std::vector<int>& vec)
    {
        using std::swap;
        swap(vec, m_vec);   // "move" vec into member vector
    }

private:
    std::vector<int> m_vec;
};

// usage:
std::vector<int> v(100, 1337);
Foo foo(v);
// v.empty() == true

The problem with this approach is that its not evident to the user that their vector will be moved into the class Foo. Is there a best practice solution to this kind of problem? Thanks in advance!

like image 918
rozina Avatar asked Aug 26 '14 14:08

rozina


People also ask

What is Move semantics in C++?

Move semantics allows you to avoid unnecessary copies when working with temporary objects that are about to evaporate, and whose resources can safely be taken from that temporary object and used by another.

How do you pass a vector to a constructor?

Begin Declare a class named as vector. Declare vec of vector type. Declare a constructor of vector class. Pass a vector object v as a parameter to the constructor.

Is STD Vector moveable?

It does not require MoveInsertable for the value type. The time complexity requirement is: "constant", btw. std::vector typically stores some pointers plus the allocator. When move-constructing a std::vector , only pointers and the allocator have to be moved.

Are move constructor automatically generated?

If a copy constructor, copy-assignment operator, move constructor, move-assignment operator, or destructor is explicitly declared, then: No move constructor is automatically generated. No move-assignment operator is automatically generated.


2 Answers

You could define a type wrapping a reference, and a function to wrap it, to give something similar to move semantics at the call site. Something along the lines of

template <typename T> struct move_ref {
    explicit move_ref(T & ref) : ref(ref) {}
    T & ref;
};

template <typename T> move_ref<T> move(T & t) {return move_ref<T>(t);}

Foo(move_ref< std::vector<int> > vec)
{
    using std::swap;
    swap(vec.ref, m_vec);   // "move" vec into member vector
}

Foo foo(move(v));

Alternatively, Boost has a library to allow move semantics without C++11.

like image 77
Mike Seymour Avatar answered Nov 13 '22 12:11

Mike Seymour


You may use some wrapper with explicit name:

template <typename T>
class MyMove
{
public:
    explicit MyMove(T& t) : t(t) {}

    T& get() {return t;}
private:
    T& t;
};

template <typename T>
MyMove<T> myMove(T& t) { return MyMove<T>(t); }

And then

class Foo
{
public:
    Foo(MyMove<std::vector<int>> vec)
    {
        using std::swap;
        swap(vec.get(), m_vec);   // "move" vec into member vector
    }

private:
    std::vector<int> m_vec;
};

usage:

std::vector<int> v(100, 1337);
Foo foo(myMove(v));
like image 40
Jarod42 Avatar answered Nov 13 '22 13:11

Jarod42