Viridya
Viridya

Reputation: 640

Fill vector with constructor call

I have two classes, one derive from the other. I would like to allocate an std:vector which is fill of the derived class. The tricky question is that I want it to call the move constructor written in the base class.

Here is the code:

class Base{
    public:
    size_t size;
    double* buff;

    Base(size_t _size):size(_size){
        buff = new double[size];
    }

    Base() = delete;
    Base operator=(const Base&) = delete;
    Base(const Base&) = delete;

    Base(Base&& b):size(b.size), buff(b.buff){
        b.buff = nullptr;
    }
    Base operator=(Base&& b){
        size = b.size;
        buff = b.buff;
        b.buff = nullptr;
    }
};

class Derive : public Base{
    public:
    Derive(size_t _size):Base(_size){};
    Derive() = delete;
    Derive operator=(const Derive&) = delete;
    Derive(const Derive&) = delete;

    Derive(Derive&& b):Base(move(b)){}
    Derive operator=(Derive&& b){
        Base::operator=(move(b));
    }
};

/********/

vector<Derive> v(10, move(Derive(5)));

g++ is telling me

error: use of deleted function ‘Derive::Derive(const Derive&)’
 { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }

and I don't understand what I am supposed to do.

Upvotes: 3

Views: 2296

Answers (3)

Nir Friedman
Nir Friedman

Reputation: 17724

An alternative solution is to write your own version of fill_n that can handle this use case. The typical fill_n does copies the same as the vector constructor, but we can write a more modern style one.

template <class T, class OutputIt, class Size, class .. Args>
OutputIt emplace_fill_n(OutputIt first, Size count, const Args& ... args)
{
    for (Size i = 0; i != count; ++i) {
        *first = T(args...);
        ++first;
    }
}

Usage:

vector<Derive> v();
v.reserve(10);
emplace_fill_n<Derive>(back_inserter(v), 10);

Upvotes: 1

NathanOliver
NathanOliver

Reputation: 181068

The problem here is that std::vector(count, object) copies object, count times, into the vector. You cannot move from it since you can only move an object into a single object.

If your class is not copyable then you will not be able to use it. You can however use

std::vector<Type> foo;
foo.reserve(count);
for (int i = 0; i < count; ++i)
    foo.emplace_back(Types_parmeters);

Upvotes: 6

Serge Ballesta
Serge Ballesta

Reputation: 149185

You are trying to build a vector of 10 elements from one single source. This is not possible because once the source element has been moved once, it is left in an undeterminated state.

For that reason, this constructor is specified in draft n4296 for C++14 to use the copy constructor (emphasize mine):

23.3.6.2 vector constructors, copy, and assignment [vector.cons]
...
vector(size_type n, const T& value, const Allocator& = Allocator());
Effects: Constructs a vector with n copies of value, using the specified allocator.
Requires: T shall be CopyInsertable into *this. ...

Upvotes: 5

Related Questions