mercredi 26 août 2015

VStudio 2012 Create custom allocator for container of move-only type

I am trying to create an stl container of a move-only type that uses its own allocator in VStudio 2012.

The trouble is: it seems as though I have to provide a construct function for the allocator which in turn needs access to a public copy constructor on the contained type.

I either get:

error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'

or

error C2039: 'construct' : is not a member of 'MyAllocator'

The same code works in clang so I suspect the problem is due to Microsoft but can anyone suggest a possible work around?

This is my code for minimal reproduction

#include <memory>
#include <vector>

using namespace std;

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


template<class t_other>
struct rebind
{
    typedef MyAllocator<t_other> other;
};

MyAllocator():m_id(0) {}
MyAllocator(int id):m_id(id){}

template <class T> 
MyAllocator(const MyAllocator<T>& other)
    :m_id(other.getId())
{

}  

T* allocate(std::size_t n)
{
    return reinterpret_cast<T*>(malloc(sizeof(T) * n));
}

void deallocate(T* p, std::size_t n)
{
    free(p);
}

int getId() const{ return m_id;}


//Have to add these although should not be necessary
void construct(pointer mem, const_reference value)
{
    std::_Construct(mem, value);      
}

void destroy(pointer mem)
{
    std::_Destroy(mem);
}

private:
    int m_id;
};

template <class T1, class U>
bool operator==(const MyAllocator<T1>& lhs, const MyAllocator<U>& rhs)
{
    return lhs.getId() == rhs.getId() ;
}

template <class T1, class U>
bool operator!=(const MyAllocator<T1>&, const MyAllocator<U>&)
{
    return lhs.getId()  != rhs.getId();
}

//define a move only type
typedef unique_ptr<uint32_t> MyIntPtr;

//define a container based on MyIntPtr and MyAllocator
typedef vector<MyIntPtr, MyAllocator<MyIntPtr> > MyVector;

int main(int argc, char* argv[])
{
   MyAllocator<MyIntPtr> alloc1(1);

   MyVector vec(alloc1);

   uint32_t* rawPtr = new uint32_t;
   *rawPtr = 18;

   vec.emplace_back(rawPtr);
   return 0;
}

Aucun commentaire:

Enregistrer un commentaire