title: C++ Problems Pushing Initializer List onto a Standard Vector If the Struct Contains a Mutex
body: <p>I'm currently working on a project in C++ in which I have a list of structs stored in a vector that have a lot processing associated with them. In order to speed things up, I've chosen to split the program across multiple threads, and the lazy way I've chosen to do this is by adding a mutex to each struct in the standard library vector. This way I can have a number of threads iterate over the array and basically take ownership of the individual elements by calling mutex.try_lock(), and either completing the associated processing with that element, or moving onto the next open one.</p>
  
  <p>Before we get started, note that the following actually <strong>does work.</strong></p>
  
  <pre><code>#include &lt;mutex&gt;
  #include &lt;vector&gt;
  
  struct foo {
      int a;
      std::mutex b;
  };
  
  void working_demo () {
      // assign by initializer list
      foo f = {.a = 1};
  }
  
  int main () {
      working_demo();
  }
  </code></pre>
  
  <p>So, I intend to populate my standard vector in a way very similar to above, and it <strong>doesn't work.</strong></p>
  
  <pre><code>#include &lt;mutex&gt;
  #include &lt;vector&gt;
  
  struct foo {
      int a;
      std::mutex b;
  };
  
  void broken_demo () {
      std::vector&lt;foo&gt; bar;
  
      // assign by initializer list
      bar.push_back({.a = 1});
  }
  
  int main () {
      broken_demo();
  }
  </code></pre>
  
  <p>Compiler Error:</p>
  
  <pre><code>clang++ -std=c++11 -Wall -Wextra -Wfatal-errors -pedantic -I./  -c -o demo.o demo.cpp
  demo.cpp:13:20: warning: designated initializers are a C99 feature [-Wc99-extensions]
      bar.push_back({.a = 1});
                     ^~~~~~
  In file included from demo.cpp:1:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/mutex:38:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/tuple:39:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/array:39:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/stdexcept:39:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/string:41:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/allocator.h:46:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/x86_64-pc-linux-gnu/bits/c++allocator.h:33:
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/ext/new_allocator.h:146:8: fatal error: call to implicitly-deleted copy constructor of 'foo'
                              _Up(std::forward&lt;_Args&gt;(__args)...)))
                              ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/alloc_traits.h:483:24: note: in instantiation of exception specification for
        'construct&lt;foo, foo&gt;' requested here
          noexcept(noexcept(__a.construct(__p, std::forward&lt;_Args&gt;(__args)...)))
                                ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:115:21: note: in instantiation of exception specification for 'construct&lt;foo, foo&gt;'
        requested here
              _Alloc_traits::construct(this-&gt;_M_impl, this-&gt;_M_impl._M_finish,
                             ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_vector.h:1201:9: note: in instantiation of function template specialization
        'std::vector&lt;foo, std::allocator&lt;foo&gt; &gt;::emplace_back&lt;foo&gt;' requested here
        { emplace_back(std::move(__x)); }
          ^
  demo.cpp:13:9: note: in instantiation of member function 'std::vector&lt;foo, std::allocator&lt;foo&gt; &gt;::push_back' requested here
      bar.push_back({.a = 1});
          ^
  demo.cpp:6:16: note: copy constructor of 'foo' is implicitly deleted because field 'b' has a deleted copy constructor
      std::mutex b;
                 ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/std_mutex.h:94:5: note: 'mutex' has been explicitly marked deleted here
      mutex(const mutex&amp;) = delete;
      ^
  
  </code></pre>
  
  <p>I'm fairly certain that this is saying the reason this won't work is that the structure is attempting to call the copy constructor for the mutex, which in fact does not have a copy constructor. I explicitly don't want to do be doing this. </p>
  
  <p>My initial thought is that in order to make sure it doesn't even try to call the copy constructor for the mutex, I can create my own constructor for my class and basically explicitly leave out the copying for the mutex. This method would look like this - <strong>but it also doesn't work.</strong></p>
  
  <pre><code>#include &lt;mutex&gt;
  #include &lt;vector&gt;
  
  struct foo {
      foo (int A): a(A) {;}
  
      int a;
      std::mutex b;
  };
  
  void broken_demo () {
      std::vector&lt;foo&gt; bar;
  
      // assign by initializer list
      bar.emplace_back(1);
  }
  
  int main () {
      broken_demo();
  }
  </code></pre>
  
  <p>Compiler Error:</p>
  
  <pre><code>clang++ -std=c++11 -Wall -Wextra -Wfatal-errors -pedantic -I./  -c -o demo.o demo.cpp
  In file included from demo.cpp:2:
  In file included from /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/vector:65:
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_construct.h:75:38: fatal error: call to implicitly-deleted copy constructor of 'foo'
      { ::new(static_cast&lt;void*&gt;(__p)) _T1(std::forward&lt;_Args&gt;(__args)...); }
                                       ^   ~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:83:8: note: in instantiation of function template specialization
        'std::_Construct&lt;foo, foo&gt;' requested here
                  std::_Construct(std::__addressof(*__cur), *__first);
                       ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:134:2: note: in instantiation of function template specialization
        'std::__uninitialized_copy&lt;false&gt;::__uninit_copy&lt;std::move_iterator&lt;foo *&gt;, foo *&gt;' requested here
          __uninit_copy(__first, __last, __result);
          ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:289:19: note: in instantiation of function template specialization
        'std::uninitialized_copy&lt;std::move_iterator&lt;foo *&gt;, foo *&gt;' requested here
      { return std::uninitialized_copy(__first, __last, __result); }
                    ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/stl_uninitialized.h:310:19: note: in instantiation of function template specialization
        'std::__uninitialized_copy_a&lt;std::move_iterator&lt;foo *&gt;, foo *, foo&gt;' requested here
        return std::__uninitialized_copy_a
                    ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:473:10: note: in instantiation of function template specialization
        'std::__uninitialized_move_if_noexcept_a&lt;foo *, foo *, std::allocator&lt;foo&gt; &gt;' requested here
                  = std::__uninitialized_move_if_noexcept_a
                         ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/vector.tcc:121:4: note: in instantiation of function template specialization 'std::vector&lt;foo,
        std::allocator&lt;foo&gt; &gt;::_M_realloc_insert&lt;int&gt;' requested here
            _M_realloc_insert(end(), std::forward&lt;_Args&gt;(__args)...);
            ^
  demo.cpp:15:9: note: in instantiation of function template specialization 'std::vector&lt;foo, std::allocator&lt;foo&gt; &gt;::emplace_back&lt;int&gt;' requested here
      bar.emplace_back(1);
          ^
  demo.cpp:8:16: note: copy constructor of 'foo' is implicitly deleted because field 'b' has a deleted copy constructor
      std::mutex b;
                 ^
  /usr/sup/bin/../lib/gcc/x86_64-pc-linux-gnu/9.1.0/../../../../include/c++/9.1.0/bits/std_mutex.h:94:5: note: 'mutex' has been explicitly marked deleted here
      mutex(const mutex&amp;) = delete;
      ^
  1 error generated.
  </code></pre>
  
  <p>Any thoughts on a solution to this? I'm hoping to keep the code relatively simple, but I'm uncertain how to make the standard vector behave, or at least use it properly.</p>