0

I have this file:

A.h

struct B;

struct A
{
    A(... B &b) :
        b(b) {}

    B &b;
};

And B.h:

#include "A.h"
struct B{
...
std::vector<A> as;
}

And this code:

std::vector<A> manya;
std::vector<B> bs;
//fill bs
for(size_t i=0; i<bs.size(); i++)
  manya.insert(manya.end(), bs[i].as.begin(), bs[i].as.end());

However, I get this error (where A=FindAffineShapeArgs and B=Wrapper):

/usr/include/c++/5/bits/stl_algobase.h(564): error: function "FindAffineShapeArgs::operator=(const FindAffineShapeArgs &)" (declared implicitly) cannot be referenced -- it is a deleted function
        *--__result = std::move(*--__last);
                    ^
          detected during:
            instantiation of "_BI2 std::__copy_move_backward<true, false, std::random_access_iterator_tag>::__copy_move_b(_BI1, _BI1, _BI2) [with _BI1=FindAffineShapeArgs *, _BI2=FindAffineShapeArgs *]" at line 606
            instantiation of "_BI2 std::__copy_move_backward_a<_IsMove,_BI1,_BI2>(_BI1, _BI1, _BI2) [with _IsMove=true, _BI1=FindAffineShapeArgs *, _BI2=FindAffineShapeArgs *]" at line 615
            instantiation of "_BI2 std::__copy_move_backward_a2<_IsMove,_BI1,_BI2>(_BI1, _BI1, _BI2) [with _IsMove=true, _BI1=FindAffineShapeArgs *, _BI2=FindAffineShapeArgs *]" at line 686
            instantiation of "_BI2 std::move_backward(_BI1, _BI1, _BI2) [with _BI1=FindAffineShapeArgs *, _BI2=FindAffineShapeArgs *]" at line 636 of "/usr/include/c++/5/bits/vector.tcc"
            instantiation of "void std::vector<_Tp, _Alloc>::_M_range_insert(std::vector<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _Tp=FindAffineShapeArgs, _Alloc=std::allocator<FindAffineShapeArgs>, _ForwardIterator=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>]" at line 1377 of "/usr/include/c++/5/bits/stl_vector.h"
            instantiation of "void std::vector<_Tp, _Alloc>::_M_insert_dispatch(std::vector<_Tp, _Alloc>::iterator, _InputIterator, _InputIterator, std::__false_type) [with _Tp=FindAffineShapeArgs, _Alloc=std::allocator<FindAffineShapeArgs>, _InputIterator=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>]" at line 1100 of "/usr/include/c++/5/bits/stl_vector.h"
            instantiation of "std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::const_iterator, _InputIterator, _InputIterator) [with _Tp=FindAffineShapeArgs, _Alloc=std::allocator<FindAffineShapeArgs>, _InputIterator=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>, <unnamed>=void]" at line 382 of
                      "/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Descriptors/hesaff/pyramid.cpp"

/usr/include/c++/5/bits/stl_algobase.h(340): error: function "FindAffineShapeArgs::operator=(const FindAffineShapeArgs &)" (declared implicitly) cannot be referenced -- it is a deleted function
          *__result = *__first;
                    ^
          detected during:
            instantiation of "_OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II=FindAffineShapeArgs *, _OI=FindAffineShapeArgs *]" at line 402
            instantiation of "_OI std::__copy_move_a<_IsMove,_II,_OI>(_II, _II, _OI) [with _IsMove=false, _II=FindAffineShapeArgs *, _OI=FindAffineShapeArgs *]" at line 440
            instantiation of "_OI std::__copy_move_a2<_IsMove,_II,_OI>(_II, _II, _OI) [with _IsMove=false, _II=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>, _OI=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>]" at line 472
            instantiation of "_OI std::copy(_II, _II, _OI) [with _II=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>, _OI=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>]" at line 637 of "/usr/include/c++/5/bits/vector.tcc"
            instantiation of "void std::vector<_Tp, _Alloc>::_M_range_insert(std::vector<_Tp, _Alloc>::iterator, _ForwardIterator, _ForwardIterator, std::forward_iterator_tag) [with _Tp=FindAffineShapeArgs, _Alloc=std::allocator<FindAffineShapeArgs>, _ForwardIterator=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>]" at line 1377 of "/usr/include/c++/5/bits/stl_vector.h"
            instantiation of "void std::vector<_Tp, _Alloc>::_M_insert_dispatch(std::vector<_Tp, _Alloc>::iterator, _InputIterator, _InputIterator, std::__false_type) [with _Tp=FindAffineShapeArgs, _Alloc=std::allocator<FindAffineShapeArgs>, _InputIterator=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>]" at line 1100 of "/usr/include/c++/5/bits/stl_vector.h"
            instantiation of "std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::const_iterator, _InputIterator, _InputIterator) [with _Tp=FindAffineShapeArgs, _Alloc=std::allocator<FindAffineShapeArgs>, _InputIterator=__gnu_cxx::__normal_iterator<FindAffineShapeArgs *, std::vector<FindAffineShapeArgs, std::allocator<FindAffineShapeArgs>>>, <unnamed>=void]" at line 382 of
                      "/home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Descriptors/hesaff/pyramid.cpp"

compilation aborted for /home/luca/Dropbox/HKUST/CloudCache/cloudcache/CloudCache/Descriptors/hesaff/pyramid.cpp (code 2)

Why this happens?

This could be related to this but for a different case

Community
  • 1
  • 1
justHelloWorld
  • 6,478
  • 8
  • 58
  • 138
  • It has nothing to do with circular dependencies or vectors (or omp even). The error mentions `operator=`. Try writing a [mcve] and you'll see what is going on. – juanchopanza Apr 21 '17 at 19:12

1 Answers1

1

The issue is that your struct A has a reference member B& b. Since references cannot be reassigned, the compiler can't implicitly generate a copy- or a move-assignment operator for you.

However, for this particular overload of std::vector<T>::insert, the standard ([sequence.reqmts]/4) states

Requires: T shall be EmplaceConstructible into X from *i. For vector and deque, T shall also be MoveInsertable into X, MoveConstructible, MoveAssignable, and swappable (17.6.3.2). [...]

Thats why the compiler complains about the implicitly deleted assignment operators.

If you really want that to be a reference member, you can use std::reference_wrapper<B> instead of B& inside the struct A.

Corristo
  • 4,911
  • 1
  • 20
  • 36
  • I can't use `std::reference_wrapper` because I get a incomplete struct error – justHelloWorld Apr 21 '17 at 20:40
  • @justHelloWorld Which compiler are you using? It works fine with gcc 6.3 and clang 4.0, see [here](https://wandbox.org/permlink/G3rf00u75ql6Wife). – Corristo Apr 21 '17 at 20:47
  • @justHelloWorld Did you maybe forget to `#include `? – Corristo Apr 21 '17 at 20:59
  • yes, missing `functional` was the problem. Can you tell me a little bit more about `std::reference_wrapper` and how this solved the problem? I've never seen it before. – justHelloWorld Apr 21 '17 at 21:45
  • 1
    @justHelloWorld A [std::reference_wrapper](http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper) is just a class that acts like it is a reference (it has an implicit conversion to `T&`, can be constructed from a `T&`, if `T` is a function type you can even call it like you normally do with a reference to a function object), but also implements assignment so that it behaves like a regular type. It was designed so that you can put references to objects in containers that normally don't support storing references. It probably is best to read the reference I linked above. – Corristo Apr 21 '17 at 21:55
  • Thanks for your clarification. What if I want to use `const B &b` instead of `B &b`? – justHelloWorld Apr 22 '17 at 00:19
  • 1
    @justHelloWorld Then you create a `std::reference_wrapper` and use `std::cref` instead of `std::ref` to create the reference wrapper from the `B&`/`B const&` in the constructor of `A`. – Corristo Apr 22 '17 at 00:22