使boost :: fast_pool_allocator可以使用可变参数模板(emplace)

时间:2015-05-04 18:06:47

标签: c++ c++11 boost

我尝试使用boost::fast_pool_allocator作为std::list的分配器,但无法找到使用可变参数模板的construct()的{​​{3}}。< / p>

#include <list>
#include <utility>

#include <boost/pool/pool_alloc.hpp>

int main()
{
    typedef std::pair<int, int> Pair;
    std::list<Pair, boost::fast_pool_allocator<Pair>> list;

    list.emplace(list.begin(), 1, 2);
}

无法使用以下错误进行编译(缩短):

stl_list.h:514:8: error: no matching function for call to ‘boost::fast_pool_allocator<blah>::construct(std::list<bleh>::_Node*&, int, int)'

查看overload,似乎boost::fast_pool_allocator只有construct()的前C ++ 11版本(指针和const_reference)。

请注意,将列表定义为std::list<Pair>(即使用默认分配器)可以正常工作。

有解决方法吗?任何适配器或某种定义分配器特征的方法?我是分配者的新手,所以这对我来说是一块黑暗的土地。

我可以使用

list.emplace(list.begin(), Pair(1, 2));

但是1)我在生产中使用的实际类比我用于示例的Pair复杂得多,性能是最重要的(因此我可以真正使用就地构造),并且理想情况下,我希望替换std::allocator,因此我可以通过单行更改来衡量性能差异。

我在Cygwin中用g ++ 4.9.2和1.58.0进行编译,我在linux环境(RHEL5.5)中使用g ++ 4.8.3和boost 1.55.0时遇到同样的问题。

2 个答案:

答案 0 :(得分:2)

outerLoop: for (var i:int = 0; i < 10; i++) {
    for (var j:int = 0; j < 10; j++) {
        if ( (i == 8) && (j == 0)) {
            break outerLoop;
        }
        trace(10 * i + j);
    }
}
/*
1
2
...
79
*/
或某些人。继承自template <typename T, typename UserAllocator, typename Mutex, unsigned NextSize, unsigned MaxSize > struct my_pool_allocator: boost::pool_allocator<T,UserAllocator,Mutex,NextSize,MaxSize> { using base=boost::pool_allocator<T,UserAllocator,Mutex,NextSize,MaxSize>; using base::base; template <typename U> struct rebind { using other=my_pool_allocator<U, UserAllocator, Mutex, NextSize, MaxSize>; }; using base::construct; template<class...Args> void construct(const typename base::pointer ptr, Args&&...args) { new (ptr) T(std::forward<Args>(args)...); } }; ,继承其构造函数,编写自定义fast_pool_allocator,继承rebind,并添加另一个处理varargs的construct重载。

一个人应该能够写一个&#34;现代化的分配器&#34;我怀疑为你做大部分工作的模板。

construct

上面可能存在拼写错误/错误:它只是解决方案的草图。

答案 1 :(得分:1)

Just for the record, it should be possible to use fast_pool_allocator directly with a C++11-conforming container, since the container is supposed to use allocator_traits::construct, which in turn calls the allocator's construct only if the call is well-formed ([allocator.traits.members]/p5):

template <class T, class... Args>
static void construct(Alloc& a, T* p, Args&&... args);

Effects: calls a.construct(p, std::forward<Args>(args)...) if that call is well-formed; otherwise, invokes ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...).

The problem is that libstdc++'s std::list is still not conforming to the C++11 standard; it directly calls construct on the allocator. As a workaround, Yakk's answer is good.