在其他容器中使用 boost::container::static_vector 时,gcc 编译错误“将‘const s’绑定到‘s&’类型的引用丢弃限定符”

Posted

技术标签:

【中文标题】在其他容器中使用 boost::container::static_vector 时,gcc 编译错误“将‘const s’绑定到‘s&’类型的引用丢弃限定符”【英文标题】:gcc compile error "binding ‘const s’ to reference of type ‘s&’ discards qualifiers" when using boost::container::static_vector in other container 【发布时间】:2018-09-14 15:47:57 【问题描述】:

在 std::vector 等另一个容器中使用 boost::container::static_vector 时,gcc 返回编译错误。下面的测试用例重现了错误:

#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);

在 Ubuntu Xenial 上遵循 g++ template_test2.cpp 会导致以下错误:

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;

仅当struct s 包含静态向量时才会出现此错误。此错误的原因是什么,是否有可用的解决方法?

【问题讨论】:

【参考方案1】:

编译器生成的默认复制赋值运算符好像有签名

s& operator= (s&);

并且您的代码在fill 算法的这一行中失败(在resize 方法中以某种方式调用):

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

因为__value 是对s 对象的常量引用,它不能作为参数传递给 operator=(s&amp;)(常量对象不能修改)。

关于为类生成默认复制赋值运算符,您可以阅读here。 static_vector 的实现有些奇怪,默认复制赋值运算符将 s&amp; 作为参数而不是 const s&amp;

要解决此问题,您可以实现您自己的此运算符版本:

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

【讨论】:

谢谢,这或多或少也是我得出的结论。我只是在检查是否有遗漏的东西。

以上是关于在其他容器中使用 boost::container::static_vector 时,gcc 编译错误“将‘const s’绑定到‘s&’类型的引用丢弃限定符”的主要内容,如果未能解决你的问题,请参考以下文章

Boost.Container `dlmalloc` 和 `jemalloc`

.select_on_container_copy_construction 左侧的 C++ boost::container::vector 必须具有类/结构/联合

如何修改boost多索引的只读元素?

Boost.Container flat_map 和 std::string_view

Boost::multi_index_container 具有不同的键和元素类型

boost::container::vector 和 std::vector 有啥区别