I cannot use mutex along with vector

167 Views Asked by At

I have trouble compiling the following code.

#include <vector>
#include <mutex>


class A
{
public:
  A(){}
private:
  std::mutex a_mutex;
};


int main()
{
   std::vector<A> v;
   A a;
   v.push_back(a);
   return 0;
}

This is the error.

$ g++ test__use_of_deleted_function.cpp
In file included from /usr/include/c++/8/x86_64-redhat-linux/bits/c++allocator.h:33,
                 from /usr/include/c++/8/bits/allocator.h:46,
                 from /usr/include/c++/8/string:41,
                 from test__use_of_delete_function.cpp:1:
/usr/include/c++/8/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = A; _Args = {const A&}; _Tp = A]’:
/usr/include/c++/8/bits/alloc_traits.h:475:4:   required from ‘static void std::allocator_traits<std::allocator<_CharT> >::construct(std::allocator_traits<std::allocator<_CharT> >::allocator_type&, _Up*, _Args&& ...) [with _Up = A; _Args = {const A&}; _Tp = A; std::allocator_traits<std::allocator<_CharT> >::allocator_type = std::allocator<A>]’
/usr/include/c++/8/bits/stl_vector.h:1079:30:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = A; _Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::value_type = A]’
test__use_of_delete_function.cpp:19:17:   required from here
/usr/include/c++/8/ext/new_allocator.h:136:4: error: use of deleted function ‘A::A(const A&)’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test__use_of_delete_function.cpp:6:7: note: ‘A::A(const A&)’ is implicitly deleted because the default definition would be ill-formed:
 class A
       ^
test__use_of_delete_function.cpp:6:7: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’
In file included from /usr/include/c++/8/mutex:43,
                 from test__use_of_delete_function.cpp:3:
/usr/include/c++/8/bits/std_mutex.h:97:5: note: declared here
     mutex(const mutex&) = delete;
     ^~~~~
In file included from /usr/include/c++/8/vector:62,
                 from test__use_of_delete_function.cpp:2:
/usr/include/c++/8/bits/stl_construct.h: In instantiation of ‘void std::_Construct(_T1*, _Args&& ...) [with _T1 = A; _Args = {A}]’:
/usr/include/c++/8/bits/stl_uninitialized.h:83:18:   required from ‘static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; bool _TrivialValueTypes = false]’
/usr/include/c++/8/bits/stl_uninitialized.h:134:15:   required from ‘_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*]’
/usr/include/c++/8/bits/stl_uninitialized.h:289:37:   required from ‘_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = std::move_iterator<A*>; _ForwardIterator = A*; _Tp = A]’
/usr/include/c++/8/bits/stl_uninitialized.h:311:2:   required from ‘_ForwardIterator std::__uninitialized_move_if_noexcept_a(_InputIterator, _InputIterator, _ForwardIterator, _Allocator&) [with _InputIterator = A*; _ForwardIterator = A*; _Allocator = std::allocator<A>]’
/usr/include/c++/8/bits/vector.tcc:447:6:   required from ‘void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {const A&}; _Tp = A; _Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<A*, std::vector<A> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = A*]’
/usr/include/c++/8/bits/stl_vector.h:1085:4:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = A; _Alloc = std::allocator<A>; std::vector<_Tp, _Alloc>::value_type = A]’
test__use_of_delete_function.cpp:19:17:   required from here
/usr/include/c++/8/bits/stl_construct.h:75:7: error: use of deleted function ‘A::A(A&&)’
     { ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test__use_of_delete_function.cpp:6:7: note: ‘A::A(A&&)’ is implicitly deleted because the default definition would be ill-formed:
 class A
       ^
test__use_of_delete_function.cpp:6:7: error: use of deleted function ‘std::mutex::mutex(const std::mutex&)’
In file included from /usr/include/c++/8/mutex:43,
                 from test__use_of_delete_function.cpp:3:
/usr/include/c++/8/bits/std_mutex.h:97:5: note: declared here
     mutex(const mutex&) = delete;
     ^~~~~
2

There are 2 best solutions below

2
On

Since std::mutex's copy-constructor is deleted, you will need to define an explicit copy constructor for A.

A(const A& other) { ... }

You'll probably want to look at C++'s idiomatic rule of 4 What is the Rule of Four (and a half)?

1
On

std::mutex can neither be copied or moved.

As shown in answers like here and here, the std::mutex member should be used to implement thread safe copy and move operations for that class, while copying and moving other members of that class.

Otherwise, as shown here, one could hold a smart pointer to the class in the vector (std::vector<std::unique_ptr<A>> v; and v.push_back(std::make_unique<A>());). However, in a practical context doing this alone may not be useful enough.