无法使用自定义分配器与allocate_shared / make_shared [英] Unable to use custom allocator with allocate_shared/make_shared

查看:1352
本文介绍了无法使用自定义分配器与allocate_shared / make_shared的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的C ++ 11程序中,对于一些主动创建和删除的对象,我使用 shared_ptr< T> 发生这样的情况,标准分配器 operator new 是一个瓶颈,所以我想创建一个自己的,一次分配一堆内存,然后给 make_shared 。 Unfortunatelly,这是我第一次写一个分配器,我不知道为什么GCC无法编译以下代码:

In my C++11 program, I use shared_ptr<T> for some objects which are actively created and deleted. It so happened that standard allocator with operator new is a bottleneck, so I want to create my own one, which will allocate a bunch of memory at once and then give to to make_shared on demand. Unfortunatelly, this is the first time I write an allocator and I have no idea why GCC is unable to compile the following code:

#include <memory>

class MyAlloc {
public:
  typedef char* pointer;
  typedef const char* const_pointer;
  typedef char value_type;

  char* allocate(size_t len) {
    return new char[len];
  }

  void deallocate(char *ptr) {
    delete[] ptr;
  }
} my_alloc;

int main() {
  std::allocator_traits<MyAlloc>();
  // MyAlloc is a correct allocator, since allocator_traits can be instantiated
  // If I comment the following line of code, compilation is successful
  std::allocate_shared<int>(my_alloc, 0);
  return 0;
}

这里我有非常简单的存根分配器和一个调用 allocate_shared 。 GCC产生的错误是:

Here I have very simple stub allocator and one call to allocate_shared. The error GCC produces is:

In file included from c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\ext\alloc_traits.h:36:0,
                 from c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\stl_construct.h:61,
                 from c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\memory:64,
                 from a.cpp:1:
c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\alloc_traits.h: In substitution of 'template<class _Alloc> template<class _Tp> using rebind_traits = std::allocator_traits<typename std::__alloctr_rebind<_Alloc, _Tp>::__type> [with _Tp = std::_Sp_counted_ptr_inplace<int, MyAlloc, (__gnu_cxx::_Lock_policy)2u>; _Alloc = MyAlloc]':
c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\shared_ptr_base.h:517:33:   required from 'std::__shared_count<_Lp>::__shared_count(std::_Sp_make_shared_tag, _Tp*, const _Alloc&, _Args&& ...) [with _Tp = int; _Alloc = MyAlloc; _Args = {int}; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]'
c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\shared_ptr_base.h:986:35:   required from 'std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = MyAlloc; _Args = {int}; _Tp = int; __gnu_cxx::_Lock_policy _Lp = (__gnu_cxx::_Lock_policy)2u]'
c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\shared_ptr.h:316:64:   required from 'std::shared_ptr<_Tp>::shared_ptr(std::_Sp_make_shared_tag, const _Alloc&, _Args&& ...) [with _Alloc = MyAlloc; _Args = {int}; _Tp = int]'
c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\shared_ptr.h:598:39:   required from 'std::shared_ptr<_Tp1> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = int; _Alloc = MyAlloc; _Args = {int}]'
a.cpp:19:40:   required from here
c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\alloc_traits.h:204:66: error: invalid use of incomplete type 'struct std::__alloctr_rebind<MyAlloc, std::_Sp_counted_ptr_inplace<int, MyAlloc, (__gnu_cxx::_Lock_policy)2u>, false>'
         using rebind_traits = allocator_traits<rebind_alloc<_Tp>>;
                                                                  ^
c:\soft\mingw\lib\gcc\mingw32\4.8.1\include\c++\bits\alloc_traits.h:65:12: error: declaration of 'struct std::__alloctr_rebind<MyAlloc, std::_Sp_counted_ptr_inplace<int, MyAlloc, (__gnu_cxx::_Lock_policy)2u>, false>'
     struct __alloctr_rebind;
            ^

为什么会发生?如何正确写入分配器,以便它们使用 allocate_shared ?我知道有一些其他的操作符和类型traits是由分配器支持,但我看不到任何提示,GCC想从我。

Why does this happen? How do I write allocators correctly so that they work with allocate_shared? I know that there are some other operators and type traits that are to be supported by allocator, but I cannot see any hint about what does GCC want from me.

此外,可以对这个特定的分配器使用 char 作为 value_type (结合 shared_ptr )或类似 void shared_ptr< T> :: some_weird_stuff p>

Also, is it OK to use char as value_type for this particular allocator (in conjunction with shared_ptr) or something like void or shared_ptr<T>::some_weird_stuff is preferrable?

推荐答案

像这样..你需要它模板化,你需要重新绑定和类型以及分配和释放成员。这也是很好的有运算符。

Like this.. You need it templated, you need the rebind and the types and the allocate and deallocate members. It is also nice to have the operators..

#include <memory>

template<typename T>
struct Allocator
{
    typedef std::size_t size_type;
    typedef std::ptrdiff_t difference_type;
    typedef T* pointer;
    typedef const T* const_pointer;
    typedef T& reference;
    typedef const T& const_reference;
    typedef T value_type;

    template<typename U>
    struct rebind {typedef Allocator<U> other;};

    Allocator() throw() {};
    Allocator(const Allocator& other) throw() {};

    template<typename U>
    Allocator(const Allocator<U>& other) throw() {};

    template<typename U>
    Allocator& operator = (const Allocator<U>& other) { return *this; }
    Allocator<T>& operator = (const Allocator& other) { return *this; }
    ~Allocator() {}

    pointer allocate(size_type n, const void* hint = 0)
    {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }

    void deallocate(T* ptr, size_type n)
    {
        ::operator delete(ptr);
    }
};

template <typename T, typename U>
inline bool operator == (const Allocator<T>&, const Allocator<U>&)
{
    return true;
}

template <typename T, typename U>
inline bool operator != (const Allocator<T>& a, const Allocator<U>& b)
{
    return !(a == b);
}


int main()
{
    std::allocate_shared<int, Allocator<int>>(Allocator<int>(), 0);
}



在最低级别,分配器可能如下所示:

At the very LEAST, an allocator could look like:

template<typename T>
struct Allocator
{
    typedef T value_type;

    Allocator() noexcept {};

    template<typename U>
    Allocator(const Allocator<U>& other) throw() {};

    T* allocate(std::size_t n, const void* hint = 0)
    {
        return static_cast<T*>(::operator new(n * sizeof(T)));
    }

    void deallocate(T* ptr, size_type n)
    {
        ::operator delete(ptr);
    }
};

template <typename T, typename U>
inline bool operator == (const Allocator<T>&, const Allocator<U>&)
{
    return true;
}

template <typename T, typename U>
inline bool operator != (const Allocator<T>& a, const Allocator<U>& b)
{
    return !(a == b);
}

这也适用于 allocate_shared ..然而,作为我的人的类型,我喜欢有所有的功能..即使是不需要/使用的所述容器/函数。

This will also work for allocate_shared.. However, being the type of person I am, I prefer to have all the functions.. Even the ones not required/used by said container/function.

这篇关于无法使用自定义分配器与allocate_shared / make_shared的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆