John
John

Reputation: 821

gcc compile error "binding ‘const s’ to reference of type ‘s&’ discards qualifiers" when using boost::container::static_vector in other container

When using boost::container::static_vector in another container such as std::vector, gcc is returning a compile error. The following test case reproduces the error:

#include <boost/container/static_vector.hpp>
#include <vector>

struct s
{
    boost::container::static_vector<int,6> a;
};

int main()
{
    std::vector<s> b;
    b.resize(6);
}

Complied with g++ template_test2.cpp on Ubuntu Xenial results in the following error:

In file included from /usr/include/c++/5/bits/char_traits.h:39:0,
                 from /usr/include/c++/5/string:40,
                 from /usr/include/c++/5/stdexcept:39,
                 from /usr/include/boost/container/throw_exception.hpp:26,
                 from /usr/include/boost/container/new_allocator.hpp:24,
                 from /usr/include/boost/container/vector.hpp:28,
                 from /usr/include/boost/container/static_vector.hpp:25,
                 from template_test2.cpp:1:
/usr/include/c++/5/bits/stl_algobase.h: In instantiation of ‘typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), void>::__type std::__fill_a(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = s*; _Tp = s; typename __gnu_cxx::__enable_if<(! std::__is_scalar<_Tp>::__value), void>::__type = void]’:
/usr/include/c++/5/bits/stl_algobase.h:747:20:   required from ‘void std::fill(_ForwardIterator, _ForwardIterator, const _Tp&) [with _ForwardIterator = s*; _Tp = s]’
/usr/include/c++/5/bits/vector.tcc:469:14:   required from ‘void std::vector<_Tp, _Alloc>::_M_fill_insert(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = s; _Alloc = std::allocator<s>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<s*, std::vector<s> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = s*; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = s]’
/usr/include/c++/5/bits/stl_vector.h:1073:23:   required from ‘void std::vector<_Tp, _Alloc>::insert(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::size_type, const value_type&) [with _Tp = s; _Alloc = std::allocator<s>; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<s*, std::vector<s> >; typename std::_Vector_base<_Tp, _Alloc>::pointer = s*; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = s]’
/usr/include/c++/5/bits/stl_vector.h:716:10:   required from ‘void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type, std::vector<_Tp, _Alloc>::value_type) [with _Tp = s; _Alloc = std::allocator<s>; std::vector<_Tp, _Alloc>::size_type = long unsigned int; std::vector<_Tp, _Alloc>::value_type = s]’
template_test2.cpp:12:11:   required from here
/usr/include/c++/5/bits/stl_algobase.h:701:11: error: binding ‘const s’ to reference of type ‘s&’ discards qualifiers
  *__first = __value;

This error only occurs if struct s contains a static vector. What is the cause of this error, and is there a workaround available?

Upvotes: 2

Views: 828

Answers (1)

rafix07
rafix07

Reputation: 20969

It looks like the default copy assigment operator generated by compiler has signature

s& operator= (s&);

and your code fails in this line of fill algorithm (it is called somehow in resize method):

  for (; __first != __last; ++__first)
      *__first = __value;  // <----- call operator=(s&) passing const s& object

because __value is const reference to s object and it cannot be passed as argument to operator=(s&) (const object cannot be modified).

About generating default copy assignment operator for classes you can read here. There is something strange with implementation of static_vector that default copy assignment operator takes s& as argument instead of const s&.

To resolve this issue you can implement your own version of this operator:

 s& operator = (const s& other) {
     a = other.a;
     return *this;
 }

Upvotes: 1

Related Questions