Boost池分配器不会使用g ++中的std :: allocate_shared进行编译

时间:2014-10-16 04:36:57

标签: c++ c++11 boost compiler-errors g++

编辑:

澄清我期望的结果,因为我没有很好地传达它:
能够使用std::allocate_sharedboost::fast_pool_allocator作为分配方法,使用g ++ 4.8或更高版本,使用boost 1.56.0。目前这适用于g ++ 4.6,并且在4.7,4.8和4.9上失败。

要明确的是,我不打算为g ++ 4.7做这项工作。

测试代码以产生错误:

#include "boost/pool/pool.hpp"
#include "boost/pool/pool_alloc.hpp"

#include <memory>

int main(int argc, char** argv)
{
  auto fails = std::allocate_shared<int>( boost::fast_pool_allocator<int>() );

  auto works = std::allocate_shared<int>(boost::fast_pool_allocator<int>(), 5);
}

在我们的代码库中,我们将std :: allocate_shared与boost池分配器结合使用,这会导致一些讨厌的编译错误。然而,这已经在不同版本的g ++中变形和变化:
详情:64bit,(4.7,4.8)-std = c ++ 11,(4.6)-std = c ++ 0x,boost 1.56.0
4.6 - 愉快地编译 4.7 - 崩溃编译器

  

内部编译器错误:重新输入错误报告例程。请   提交完整的错误报告,如果适用,请提供预处理的来源。看到    作为指示。   预处理的源存储在/tmp/cca0Emq9.out文件中,请附上   这是你的bug报告。

4.8 - 令人讨厌的编译错误

/XXXXXXXXXX/boost/boost/pool/pool_alloc.hpp:399:
     

错误:使用已删除的函数'std :: _ Sp_counted_ptr_inplace,   (__gnu_cxx :: _ Lock_policy)2U&GT; :: _ Sp_counted_ptr_inplace(常量   的std :: _ Sp_counted_ptr_inplace,   (__gnu_cxx :: _ Lock_policy)2U&GT;&安培)”            {new(ptr)T(t); }              ^

     

/ usr / include / c ++ / 4.8 / bits / shared_ptr_base.h:198:错误:   “的std :: _ Sp_counted_base&LT; _Lp&GT; :: _ Sp_counted_base(常量   std :: _ Sp_counted_base&lt; _Lp&gt;&amp;)[with __gnu_cxx :: _ Lock_policy _Lp =   (__gnu_cxx :: _ Lock_policy)2u]'是私有的          _Sp_counted_base(_Sp_counted_base const&amp;)=删除;          ^   /usr/include/c++/4.8/bits/shared_ptr_base.h:379:错误:在此内   上下文        class _Sp_counted_ptr_inplace final:public _Sp_counted_base&lt; _Lp&gt;              ^

     

/ usr / include / c ++ / 4.8 / bits / shared_ptr_base.h:379:错误:使用已删除   function'std :: _ Sp_counted_base&lt; _Lp&gt; :: _ Sp_counted_base(const   std :: _ Sp_counted_base&lt; _Lp&gt;&amp;)[with __gnu_cxx :: _ Lock_policy _Lp =   (__gnu_cxx :: _ Lock_policy)2U]”

     

/ usr / include / c ++ / 4.8 / bits / shared_ptr_base.h:198:错误:在这里声明          _Sp_counted_base(_Sp_counted_base const&amp;)=删除;          ^

4.9 - 讨厌的编译错误(略有不同)

  

/XXXXXXXXXXX/boost/boost/pool/pool_alloc.hpp:399:错误:使用   删除函数'std :: _ Sp_counted_ptr_inplace,   (__gnu_cxx :: _ Lock_policy)2U&GT; :: _ Sp_counted_ptr_inplace(常量   的std :: _ Sp_counted_ptr_inplace,   (__gnu_cxx :: _ Lock_policy)2U&GT;&安培)”        {new(ptr)T(t); }          ^

     

/ usr / include / c ++ / 4.9 / bits / shared_ptr_base.h:203:错误:   “的std :: _ Sp_counted_base&LT; _Lp&GT; :: _ Sp_counted_base(常量   std :: _ Sp_counted_base&lt; _Lp&gt;&amp;)[with __gnu_cxx :: _ Lock_policy _Lp =   (__gnu_cxx :: _ Lock_policy)2u]'是私有的          _Sp_counted_base(_Sp_counted_base const&amp;)=删除;          ^

     

/ usr / include / c ++ / 4.9 / bits / shared_ptr_base.h:494:错误:在此内   上下文        class _Sp_counted_ptr_inplace final:public _Sp_counted_base&lt; _Lp&gt;              ^

     

/ usr / include / c ++ / 4.9 / bits / shared_ptr_base.h:494:错误:使用已删除   function'std :: _ Sp_counted_base&lt; _Lp&gt; :: _ Sp_counted_base(const   std :: _ Sp_counted_base&lt; _Lp&gt;&amp;)[with __gnu_cxx :: _ Lock_policy _Lp =   (__gnu_cxx :: _ Lock_policy)2u]'

我花了很多钱 时间试图找到这个底部,我会得到一些帮助 如果有人更熟悉其内部运作,我们将不胜感激 这些组件。

2 个答案:

答案 0 :(得分:3)

我花了很多时间查看不同的编译器版本,假设这是一个编译器错误,如g ++ 4.7中的崩溃和其他回答者/评论者的评论所暗示的那样。然而,在回到编译错误并挖掘它们一段时间之后,我设法最终以一定程度的特异性理解编译错误的原因。

所以这个问题确实存在于boost::fast_pool_allocatorboost::pool_allocator中,回想起来似乎有点明显。问题的基本关键是boost allocators construct method是根据c ++ 98标准分配器规范实现的,并且有一个构造方法,它采用单个const&amp; param用于复制构造新的位置对象。 c ++ 11样式使用可变参数模板,并且args被传递给通过placement new创建的对象的构造函数。在我的测试代码的特定情况下,它是不会将初始化值传递给导致错误的std::allocate_shared的变体。手头的核心问题是c ++ 11 std::allocate_shared试图将可变数量的参数传递给只需要一个的construct()方法。在我的测试中,当传入一个值时,我可以断开构造方法,并且不会为其他变体调用它。例如,如果要分配std::pair<>(2个参数),则根本不调用构造方法,并且必须使用其他一些机制。我对此进行了一些跟踪,看起来std::allocate_shared在内部包装了构造调用,如果对构造的调用没有匹配,则调用另一个方法(通过隐式函数查找)直接构造对象。下面的top方法调用分配器的construct()方法,最下面的方法直接调用对象:

alloc_traits.h:250-61

template<typename _Tp, typename... _Args>
static typename
    enable_if<__construct_helper<_Tp, _Args...>::value, void>::type
    _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args)
{ __a.construct(__p, std::forward<_Args>(__args)...); }

template<typename _Tp, typename... _Args>
static typename
enable_if<__and_<__not_<__construct_helper<_Tp, _Args...>>,
         is_constructible<_Tp, _Args...>>::value, void>::type
    _S_construct(_Alloc&, _Tp* __p, _Args&&... __args)
{ ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); }

这是我有时间真正确定编译错误的来源,但这足以让我为这个问题整理一个简单而有效的解决方案。

这里的解决方案很简单;需要更新boost以使用新的c ++ 11分配器规范。这样做实际上非常简单;在pool_alloc.hpp中替换所有实例:

void construct(const pointer ptr, const value_type & t)
{ new (ptr) T(t); }

template <typename... Args>
void construct(const pointer ptr, Args&&... args)
{
  new (ptr) T( std::forward<Args>(args)... );
}

似乎这是一个错误,提升没有更新他们的代码用于c ++ 11支持,但事实上g ++ 5.0(我确认)编译没有问题意味着添加此支持不是必须的向前。可能是std::allocate_shared旨在向后兼容旧的分配器接口,4.7,4.8和4.9的崩溃和编译错误是支持被破坏。我将在增强错误跟踪器上发布一张票,看看他们认为这笔交易是什么:boost trac ticket

答案 1 :(得分:2)

由于这似乎是libstdc ++的一个问题(?),您可以使用标准库函数的boost等效代替boost::allocate_shared。包括<boost/make_shared.hpp>。这是一个 Coliru demo ,显示了四个不同的GCC版本,可以正常编译。正如我在评论中提到的,std::allocate_shared适用于GCC的主干版本和libc ++。我无法找到与此问题相关的现有错误报告,但您可以为GCCBoost提交一个。