2

I've been struggeling a lot lately with move and copy constructors and can't seem to find the awnser on my own. The structure is fairly simple. A class OWUP which holds a std::unique_ptr to an object (in this example an int), a class One which is a simple wrapper around std::vector of OWUP's and class Two which is a simple wrapper std::vector of One's.

#include <memory>
#include <vector>

class OWUP {
public:
    OWUP()
    : data(nullptr)
    { }

    OWUP(const OWUP &) = delete;
    OWUP &operator=(const OWUP &) = delete; 
    OWUP(OWUP &&) noexcept = default;
    OWUP &operator=(OWUP &&) noexcept = default; 

    std::unique_ptr<int> data; 
};

class One {
public:
    One(std::size_t numof_datas)
    : datas(numof_datas)
    { }

    One(const One &) = delete;
    One &operator=(const One &) = delete; 
    One(One &&) noexcept = default;
    One &operator=(One &&) noexcept = default; 

    std::vector<OWUP> datas;
};

class Two {
public:
    Two(std::size_t numof_ones, std::size_t num_of_datas)
    : ones(numof_ones, One(num_of_datas))
    { }

    Two(const Two &) = delete;
    Two &operator=(const Two &) = delete; 
    Two(Two &&) noexcept = default;
    Two &operator=(Two &&) noexcept = default;

    std::vector<One> ones;
}; 

The code gets the following error code with g++ -std=c++14 example.cpp

In file included from /usr/include/c++/7.3.1/memory:64:0,
                 from example.cpp:1:
/usr/include/c++/7.3.1/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = One; _Args = {const One&}]':
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:210:18:   required from 'static _ForwardIterator std::__uninitialized_fill_n<_TrivialValueType>::__uninit_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One; bool _TrivialValueType = false]'
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:255:17:   required from '_ForwardIterator std::uninitialized_fill_n(_ForwardIterator, _Size, const _Tp&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One]'
/usr/include/c++/7.3.1/bits/stl_uninitialized.h:366:39:   required from '_ForwardIterator std::__uninitialized_fill_n_a(_ForwardIterator, _Size, const _Tp&, std::allocator<_Tp2>&) [with _ForwardIterator = One*; _Size = long unsigned int; _Tp = One; _Tp2 = One]'
/usr/include/c++/7.3.1/bits/stl_vector.h:1337:33:   required from 'void std::vector<_Tp, _Alloc>::_M_fill_initialize(std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = One; _Alloc = std::allocator<One>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = One]'
/usr/include/c++/7.3.1/bits/stl_vector.h:298:27:   required from 'std::vector<_Tp, _Alloc>::vector(std::vector<_Tp, _Alloc>::size_type, const value_type&, const allocator_type&) [with _Tp = One; _Alloc = std::allocator<One>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = One; std::vector<_Tp, _Alloc>::allocator_type = std::allocator<One>]'
example.cpp:40:39:   required from here
/usr/include/c++/7.3.1/bits/stl_construct.h:75:7: error: use of deleted function 'One::One(const One&)'
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
example.cpp:29:3: note: declared here
   One(const One &) = delete;
   ^~~

I've tried my best to force it to use move constructors. I also tried to create my own move constructors with std::move, but that resulted int the same compile error. I'm aware that std::vector tests for move_if_noexcept(), but for can't find out why it doesn't. What is it that i'm doing wrong?

0

2 Answers 2

8

Because the problem is here:

Two(std::size_t numof_ones, std::size_t num_of_datas)
: ones(numof_ones, One(num_of_datas))
{ }

You can't move from One you create here, you really need to copy from it numof_ones times.

Sign up to request clarification or add additional context in comments.

6 Comments

Hmm I don't know if i fully understand your awnser, but removing One(num_of_datas) and manually adding the One(num_of_datas) numof_ones number of times in a loop does fix the problem. Is this the fix you meant?
@73nismit you're calling a constructor of vector that copies the argument. from here - 2) Constructs the container with count copies of elements with value value..
@73nismit moving an object is like moving an apple from a box to another box. The result is that last box looks like the first before the move; but you didn't need to go to the shops to get more apples. This works great if you only need 1 apple. If you need 5 apples in 5 boxes though; you're going to need to get more; in which case you need to copy the box.
Also, it doesn't say that the move constructor is deleted, it's the copyconstructor that is deleted. switch places on "move" and "copy"?
@UKmonkey I don't want to copy or move to begin with, i want to initialize the size of the 2d array
|
2

Unfortunately, there is no easy way of constructing a std::vector<One> of size numof_ones without One having a default constructor or a copy constructor. The constructor you chose takes numof_ones copies of the single value you give it into each element of the vector.

The easiest solution is probably to not initialize ones in the constructor initializer list but instead initialize it in the body of the constructor:

Two(std::size_t numof_ones, std::size_t num_of_datas) {
    ones.reserve(numof_ones);
    for (size_t i = 0; i != numof_ones; ++i) {
        ones.emplace_back(num_of_datas);
    }
}

(Technically you could probably use the std::vector constructor that takes two iterators and provide your own custom iterator but it is probably not worth the effort).

1 Comment

This is what I did to prevent the compiler errors, but I don't think it's the right way to do it though. It doesn't feel right.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.