Re: Make STL containers allocate aligned memory
On Nov 26, 6:06 pm, zr <zvir...@gmail.com> wrote:
On Nov 26, 7:32 pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 26, 5:03 pm, Maxim Yegorushkin <maxim.yegorush...@gmail.com>
wrote:
On Nov 26, 4:42 pm, zr <zvir...@gmail.com> wrote:
I need to use STL containers that allocate aligned memory.
Why?
My compiler provides an aligned_malloc routine.
It is probably provided by a library shipped with the compiler, not b=
y
compiler itself.
How can this be accomplished?
Something like this:
#include <memory>
#include <stdexcept>
template<class T, size_t alignment>
struct aligned_allocator : std::allocator<T>
{
template<class U>
struct rebind { typedef aligned_allocator<U, alignment> other=
; };
typedef std::allocator<T> base;
typedef typename base::pointer pointer;
typedef typename base::size_type size_type;
pointer allocate(size_type n)
{
if(pointer p = (pointer)aligned_malloc(n, alignment=
))
return p;
throw std::bad_alloc("aligned_allocator");
}
pointer allocate(size_type n, void const*)
{
return this->allocate(n);
}
void deallocate(pointer p, size_type)
{
aligned_free(p);
}
};
Usage is:
typedef std::vector<X, aligned_allocator<X, required_alignment>=
>
VecX;
--
Max
Max, thanks. I wrote a quick test on your proposal. Unfortunately, got
a compilation error:
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\xutility
(419) : error C2664: 'aligned_allocator<T,alignment>::aligned_allocator
(const aligned_allocator<T,alignment> &) throw()' : cannot convert
parameter 1 from 'aligned_allocator<T,alignment>' to 'const
aligned_allocator<T,alignment> &'
with
[
T=std::_Aux_cont,
alignment=64
]
and
[
T=int,
alignment=64
]
and
[
T=std::_Aux_cont,
alignment=64
]
Reason: cannot convert from 'aligned_allocator<T,alignmen=
t>'
to 'const aligned_allocator<T,alignment>'
with
[
T=int,
alignment=64
]
and
[
T=std::_Aux_cont,
alignment=64
]
No user-defined-conversion operator available that can pe=
rform
this conversion, or the operator cannot be called
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\inc=
lude
\xutility(417) : while compiling class template member function
'std::_Container_base_aux_alloc_real<_Alloc>::_Container_base_aux_alloc_r=
eal
(_Alloc)'
with
[
_Alloc=aligned_allocator<int,64>
]
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\inc=
lude
\vector(421) : see reference to class template instantiation
'std::_Container_base_aux_alloc_real<_Alloc>' being compiled
with
[
_Alloc=aligned_allocator<int,64>
]
C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\inc=
lude
\vector(439) : see reference to class template instantiation
'std::_Vector_val<_Ty,_Alloc>' being compiled
with
[
_Ty=int,
_Alloc=aligned_allocator<int,64>
]
.\main.cpp(38) : see reference to class template instanti=
ation
'std::vector<_Ty,_Ax>' being compiled
with
[
_Ty=int,
_Ax=aligned_allocator<int,64>
]
Following is the source of the test:
#include <malloc.h>
#include <memory>
#include <stdexcept>
#include <vector>
template<class T, size_t alignment>
struct aligned_allocator : std::allocator<T>
{
template<class U>
struct rebind { typedef aligned_allocator<U, alignment> other; };
typedef std::allocator<T> base;
typedef typename base::pointer pointer;
typedef typename base::size_type size_type;
pointer allocate(size_type n)
{
if(pointer p = (pointer)_aligned_malloc(n, alignment))
return p;
throw std::bad_alloc("aligned_allocator");
}
pointer allocate(size_type n, void const*)
{
return this->allocate(n);
}
void deallocate(pointer p, size_type)
{
_aligned_free(p);
}
};
int main(int argc, char* argv[])
{
std::vector<int, aligned_allocator<int, 64> > v(1024);
}
Strange, it compiles fine with M$VC 2005. It looks like
aligned_allocator needs a conversion constructor. Try adding these
constructors:
aligned_allocator()
{}
template<class U>
aligned_allocator(U const&)
{}
--
Max