custom Allocator compilation difficulties 3 - c++

Having managed to define a custom allocator, it compiles when Char=char while it doesn΄t when Char=char16_t or char32_t . The allocator allocates all Strings sequentially inside the array m ( may be seen debugging and looking at memory ).
#include <string>
#include <limits>
typedef char char8_t; // just for symmetry.
#define charSz 8 // may by 16 or 32. change by hand !
//#define CONCAT_(a,b,c) a ## b ## c
//#define CONCAT(a,b,c) CONCAT_(a,b,c)
//typedef CONCAT(char,charSz,_t) Char; // may be char8_t or char16_t or char32_t
#if charSz == 8
#define STR(s) #s
typedef char8_t Char;
#elif charSz == 16
#define STR(s) u ## #s
typedef char16_t Char;
#elif charSz == 32
#define STR(s) U ## #s
typedef char32_t Char;
#endif
typedef int32_t Token;
typedef unsigned char byte;
typedef size_t addr;addr freePos=0;Token freeT=0;
const size_t heapSize=0x400;byte m[heapSize];
addr Allocate(size_t sz){addr t=freePos;freePos+=sz;return t;}
void Deallocate(addr p,size_t sz){/**((size_t*)(m+p))=sz;*/}
using namespace std;
template <typename T>
struct Allocator {
// http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef value_type& reference;typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U> struct rebind {typedef Allocator<U> other;};
inline Allocator() {}
// The initialization of freePos and freeT is done after the class definition.
// Doing it in the class creator ins't correct because another intializer of another Allocator
// class would reinitialize that.
inline ~Allocator() {}
inline Allocator(Allocator const&) {}
inline addr address(reference r) {return (byte*)(&r)-m;}
inline addr address(const_reference r) {return (byte*)(&r)-m;}
//static inline offset_type allocate(size_type n, typename std::allocator<void>::const_pointer hint = 0)
// offset_type t=freePos;freePos+=n*sizeof(T);return t;
static inline pointer allocate(size_type n){return (pointer)(m+Allocate(n*sizeof(T)));}
static void deallocate(pointer p, size_type n){Deallocate((byte*)p-m,sizeof(T)*n);}
inline size_type max_size() const{
return std::numeric_limits<size_type>::max() / sizeof(T);
}
inline void construct(pointer p, const T& t) {}
inline void destroy(pointer p) {}
};
template <typename T>
bool operator==(Allocator<T> const &, Allocator<T> const &) { return true; }
template <typename T>
bool operator!=(Allocator<T> const &, Allocator<T> const &) { return false; }
typedef std::basic_string< Char,std::char_traits<Char>,Allocator<Char> > String;
int main(){
for (size_t i=0;i<sizeof(m);i++) m[i]=0xDD; // fill memory to be able to see changes - especially 0s
String s=STR(nice) ;
String t=STR(very nice) ;
String u=STR(good) ;
return 0;
}

Adding
template<typename U> Allocator(U){}
works !

Related

How to align memory allocated for std::vector? [duplicate]

Is it possible to make std::vector of custom structs allocate aligned memory for further processing with SIMD instructions? If it is possible to do with Allocator, does anyone happen to have such an allocator he could share?
Edit: I removed the inheritance of std::allocator as suggested by GManNickG and made the alignment parameter a compile time thing.
I recently wrote this piece of code. It's not tested as much as I would like it so go on and report errors. :-)
enum class Alignment : size_t
{
Normal = sizeof(void*),
SSE = 16,
AVX = 32,
};
namespace detail {
void* allocate_aligned_memory(size_t align, size_t size);
void deallocate_aligned_memory(void* ptr) noexcept;
}
template <typename T, Alignment Align = Alignment::AVX>
class AlignedAllocator;
template <Alignment Align>
class AlignedAllocator<void, Align>
{
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template <class U> struct rebind { typedef AlignedAllocator<U, Align> other; };
};
template <typename T, Alignment Align>
class AlignedAllocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::true_type propagate_on_container_move_assignment;
template <class U>
struct rebind { typedef AlignedAllocator<U, Align> other; };
public:
AlignedAllocator() noexcept
{}
template <class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept
{}
size_type
max_size() const noexcept
{ return (size_type(~0) - size_type(Align)) / sizeof(T); }
pointer
address(reference x) const noexcept
{ return std::addressof(x); }
const_pointer
address(const_reference x) const noexcept
{ return std::addressof(x); }
pointer
allocate(size_type n, typename AlignedAllocator<void, Align>::const_pointer = 0)
{
const size_type alignment = static_cast<size_type>( Align );
void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void
deallocate(pointer p, size_type) noexcept
{ return detail::deallocate_aligned_memory(p); }
template <class U, class ...Args>
void
construct(U* p, Args&&... args)
{ ::new(reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...); }
void
destroy(pointer p)
{ p->~T(); }
};
template <typename T, Alignment Align>
class AlignedAllocator<const T, Align>
{
public:
typedef T value_type;
typedef const T* pointer;
typedef const T* const_pointer;
typedef const T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::true_type propagate_on_container_move_assignment;
template <class U>
struct rebind { typedef AlignedAllocator<U, Align> other; };
public:
AlignedAllocator() noexcept
{}
template <class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept
{}
size_type
max_size() const noexcept
{ return (size_type(~0) - size_type(Align)) / sizeof(T); }
const_pointer
address(const_reference x) const noexcept
{ return std::addressof(x); }
pointer
allocate(size_type n, typename AlignedAllocator<void, Align>::const_pointer = 0)
{
const size_type alignment = static_cast<size_type>( Align );
void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void
deallocate(pointer p, size_type) noexcept
{ return detail::deallocate_aligned_memory(p); }
template <class U, class ...Args>
void
construct(U* p, Args&&... args)
{ ::new(reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...); }
void
destroy(pointer p)
{ p->~T(); }
};
template <typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool
operator== (const AlignedAllocator<T,TAlign>&, const AlignedAllocator<U, UAlign>&) noexcept
{ return TAlign == UAlign; }
template <typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool
operator!= (const AlignedAllocator<T,TAlign>&, const AlignedAllocator<U, UAlign>&) noexcept
{ return TAlign != UAlign; }
The implementation for the actual allocate calls is posix only but you can extent that easily.
void*
detail::allocate_aligned_memory(size_t align, size_t size)
{
assert(align >= sizeof(void*));
assert(nail::is_power_of_two(align));
if (size == 0) {
return nullptr;
}
void* ptr = nullptr;
int rc = posix_memalign(&ptr, align, size);
if (rc != 0) {
return nullptr;
}
return ptr;
}
void
detail::deallocate_aligned_memory(void *ptr) noexcept
{
return free(ptr);
}
Needs C++11, btw.
In the upcoming version 1.56, the Boost library will include Boost.Align. Among other memory alignment helpers it provides boost::alignment::aligned_allocator, which can be used a drop-in replacement for std::allocator and allows you to specify an alignment. See the documentation on https://boostorg.github.io/align/
Starting in C++17, just use std::vector<__m256i> or with any other aligned type. There's aligned version of operator new, it is used by std::allocator for aligned types (as well as by plain new-expression, so new __m256i[N] is also safe starting in C++17).
There's a comment by #MarcGlisse saying this, making this an answer to make it more visible.
Yes, it should be possible. If you put this question on google then you will get lots of sample code, below is some promising results:
https://bitbucket.org/marten/alignedallocator/wiki/Home
http://code.google.com/p/mastermind-strategy/source/browse/trunk/src/util/aligned_allocator.hpp?r=167
https://gist.github.com/1471329

std::string with a custom allocator

So I'm currently in the process of writing a memory debugger and to do that I need stl container objects to use an untracked allocator.
I have std::string peppered throughout my entire codebase, so I typedef'd it to use my untracked allocator:
typedef std::basic_string<char, std::char_traits<char>, UntrackedAllocator<char>> String;
Now when I try to do this:
String str { "Some string" };
String copy = str;
I get this error:
/usr/local/include/c++/7.1.0/ext/alloc_traits.h:95:67: error: no matching function for call to 'UntrackedAllocator<char>::UntrackedAllocator(UntrackedAllocator<char>)' { return _Base_type::select_on_container_copy_construction(__a); }
This is what my Untracked Allocator looks like:
#pragma once
#define NOMINMAX
#undef max
template <typename T>
class UntrackedAllocator {
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
public:
template<typename U>
struct rebind {
typedef UntrackedAllocator<U> other;
};
public:
inline explicit UntrackedAllocator() {}
inline ~UntrackedAllocator() {}
inline explicit UntrackedAllocator(UntrackedAllocator const&) {}
template<typename U>
inline explicit UntrackedAllocator(UntrackedAllocator<U> const&) {}
// address
inline pointer address(reference r) {
return &r;
}
inline const_pointer address(const_reference r) {
return &r;
}
// memory allocation
inline pointer allocate(size_type cnt,
typename std::allocator<void>::const_pointer = 0) {
T *ptr = (T*)malloc(cnt * sizeof(T));
return ptr;
}
inline void deallocate(pointer p, size_type cnt) {
free(p);
}
// size
inline size_type max_size() const {
return std::numeric_limits<size_type>::max() / sizeof(T);
}
// construction/destruction
inline void construct(pointer p, const T& t) {
new(p) T(t);
}
inline void destroy(pointer p) {
p->~T();
}
inline bool operator==(UntrackedAllocator const& a) { return this == &a; }
inline bool operator!=(UntrackedAllocator const& a) { return !operator==(a); }
};
This is my first time working with custom allocators so I have no idea what's going on with it. It's incredibly annoyning that I can't do str1 = str2 if one of them uses a custom allocator.
The problem is the declaration of the copy c'tors as explicit.
Changing the UntrackedAllocator copy c'tor to:
inline UntrackedAllocator(UntrackedAllocator const&) {}
Solves the compilation issue and everything works just fine:
int main() {
String str { "13" };
String copy = str;
const char* cstr = str.c_str();
int out = atoi(cstr);
}
This happens because the assignment operator of the std::basic_string that accepts const std::basic_string & requires an implicit copy construction of the allocator.

custom Allocator compilation difficulties

I am trying to create a custom allocator, but there are compilation problems.
By changing the value of the define from
#define _GLIBCXX_FULLY_DYNAMIC_STRING 0
to
#define _GLIBCXX_FULLY_DYNAMIC_STRING 1
I managed to switch from being unable to compile to being able to compile, but should it be like that? Shouldn't it be a little bit simpler ?
Does any body has experienc on that and already knows how these compilation problems may be solved.
The code the minimal required:
#include <bits/c++config.h>
#define _GLIBCXX_FULLY_DYNAMIC_STRING 0
#include <stdint.h>
#include <stddef.h>
#include <memory>
#include <string>
#include <limits>
typedef int32_t Token;
typedef unsigned char byte;
using namespace std;
template <typename T>
struct Allocator {
public:
static const size_t heapSize=0x1000;
static size_t freePos;
static Token freeT;
static byte m[heapSize];
// http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement
typedef T value_type;
typedef value_type* pointer;typedef const value_type* const_pointer;
typedef value_type& reference;typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U> struct rebind {typedef Allocator<U> other;};
inline explicit Allocator() {freeT=0;freePos=0;}
inline ~Allocator() {}
inline Allocator(Allocator const&) {} // with explicit it doesn't compile
//template<typename U>
//inline explicit Allocator(Allocator<U> const&) {}
inline pointer address(reference r) {return &r;}
inline const_pointer address(const_reference r) {return &r;}
static inline pointer allocate(size_type cnt, typename std::allocator<void>::const_pointer hint = 0){
return reinterpret_cast<pointer>(::operator new(cnt * sizeof (T)));
/* pointer allocate(size_type n, const_pointer hint = 0 ){
size_t t=freePos;freePos+=sizeof(T)*n;return t;
}
*/
}
static inline void deallocate(pointer p, size_type){
::operator delete(p);
/* pointer deallocate(pointer p,size_type n){
size_t sz=sizeof(T)*n;
*(size_t*)(m+p)=sz;
}
*/
}
inline size_type max_size() const{
return std::numeric_limits<size_type>::max() / sizeof(T);
}
inline void construct(pointer p, const T& t) { new(p) T(t); }
/*
void construct(pointer p, const T& val)
{ new ((T*) p) T(val); }
*/
inline void destroy(pointer p) { p->~T(); }
// void destroy(pointer p) { ((T*)m[p])->~T(); }
inline bool operator==(Allocator const&) {return true;}
inline bool operator!=(Allocator const& a) {return false;}
};
#endif
using namespace std;
typedef std::basic_string< char,std::char_traits<char>,Allocator<char> > String;
int main(){
String s("Nice-the-data-goes-in-my-memory");
return 0;
}
It works fine if you make the comparison operators free functions. In general, relational operators should be free functions so they can convert implicitly on both sides:
template <typename T>
bool operator==(Allocator<T> const &, Allocator<T> const &) { return true; }
template <typename T>
bool operator!=(Allocator<T> const &, Allocator<T> const &) { return false; }

custom Allocator compilation difficulties 2

I am defining a custom allocator but I need to keep pointers of the allocator as offsets. As I change the pointer definition to a "size_t" type the code doesn't compile again with no apparent clues !
The need is to create a custom allocator where the memory is addressed in a "segment:offset" style and the address of the segment ( object ) is relocatable.
#include <bits/c++config.h>
#define _GLIBCXX_FULLY_DYNAMIC_STRING 0
#include <stdint.h>
#include <stddef.h>
#include <memory>
#include <string>
#include <limits>
typedef int32_t Token;
typedef unsigned char byte;
using namespace std;
template <typename T>
struct Allocator {
public:
// http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement
typedef T value_type;
typedef std::size_t pointer;
typedef const std::size_t const_pointer;
typedef value_type& reference;typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U> struct rebind {typedef Allocator<U> other;};
static const size_t heapSize=0x1000;
static pointer freePos;
static Token freeT;
static byte m[heapSize];
inline explicit Allocator() {freeT=0;freePos=0;}
inline ~Allocator() {}
inline Allocator(Allocator const&) {} // with explicit it doesn't compile
inline pointer address(reference r) {return &r;}
inline const_pointer address(const_reference r) {return &r;}
//static inline pointer allocate(size_type n, typename std::allocator<void>::const_pointer hint = 0){
// pointer t=freePos;freePos+=n*sizeof(T);return t;
static inline pointer allocate(size_type n){pointer t=freePos;freePos+=n*sizeof(T);return t;}
static void deallocate(pointer p, size_type n){
*(pointer*)((byte*)m+p)=(pointer)(n*sizeof(T));
}
static inline void deallocate(T* p,size_type n){deallocate((pointer)((byte*)p-m),n);}
static inline void deallocate(const T* p,size_type n){deallocate((pointer)((byte*)p-m),n);}
inline size_type max_size() const{
return std::numeric_limits<size_type>::max() / sizeof(T);
}
inline void construct(pointer p, const T& t) {}
inline void destroy(pointer p) {}
};
template <typename T>
bool operator==(Allocator<T> const &, Allocator<T> const &) { return true; }
template <typename T>
bool operator!=(Allocator<T> const &, Allocator<T> const &) { return false; }
using namespace std;
typedef std::basic_string< char,std::char_traits<char>,Allocator<char> > String;
int main(){
String s("nice");
String t("very nice");
String u("good");
return 0;
}
Keep the definitions of pointer and const_pointer the way the standard library expects it to be:
typedef T* pointer;
typedef const T* const_pointer;
Add a new typedef:
typedef std::size_t offset_type;
Use offset_type instead of pointer in suitable places.
Here's a version that compiles and builds but produces Segmentation Fault at run time. I'll leave it to you to figure out that problem.
#include <bits/c++config.h>
#define _GLIBCXX_FULLY_DYNAMIC_STRING 0
#include <stdint.h>
#include <stddef.h>
#include <memory>
#include <string>
#include <limits>
typedef int32_t Token;
typedef unsigned char byte;
using namespace std;
template <typename T>
struct Allocator {
public:
// http://www.codeproject.com/Articles/4795/C-Standard-Allocator-An-Introduction-and-Implement
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef std::size_t offset_type;
typedef value_type& reference;typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template<typename U> struct rebind {typedef Allocator<U> other;};
static const size_t heapSize=0x1000;
static offset_type freePos;
static Token freeT;
static byte m[heapSize];
inline explicit Allocator() {freeT=0;freePos=0;}
inline ~Allocator() {}
inline Allocator(Allocator const&) {} // with explicit it doesn't compile
inline offset_type address(reference r) {return &r;}
inline const_pointer address(const_reference r) {return &r;}
//static inline offset_type allocate(size_type n, typename std::allocator<void>::const_pointer hint = 0)
// offset_type t=freePos;freePos+=n*sizeof(T);return t;
static inline pointer allocate(size_type n){offset_type t=freePos;freePos+=n*sizeof(T);return (pointer)t;}
static void deallocate(offset_type p, size_type n){
*(offset_type*)((byte*)m+p)=(offset_type)(n*sizeof(T));
}
static inline void deallocate(pointer p,size_type n){deallocate((offset_type)((byte*)p-m),n);}
static inline void deallocate(const_pointer* p,size_type n){deallocate((offset_type)((byte*)p-m),n);}
inline size_type max_size() const{
return std::numeric_limits<size_type>::max() / sizeof(T);
}
inline void construct(offset_type p, const T& t) {}
inline void destroy(offset_type p) {}
};
template <typename T>
typename Allocator<T>::offset_type Allocator<T>::freePos;
template <typename T>
Token Allocator<T>::freeT;
template <typename T>
byte Allocator<T>::m[Allocator::heapSize];
template <typename T>
bool operator==(Allocator<T> const &, Allocator<T> const &) { return true; }
template <typename T>
bool operator!=(Allocator<T> const &, Allocator<T> const &) { return false; }
using namespace std;
typedef std::basic_string< char,std::char_traits<char>,Allocator<char> > String;
int main(){
String s("nice");
String t("very nice");
String u("good");
return 0;
}

Making std::vector allocate aligned memory

Is it possible to make std::vector of custom structs allocate aligned memory for further processing with SIMD instructions? If it is possible to do with Allocator, does anyone happen to have such an allocator he could share?
Edit: I removed the inheritance of std::allocator as suggested by GManNickG and made the alignment parameter a compile time thing.
I recently wrote this piece of code. It's not tested as much as I would like it so go on and report errors. :-)
enum class Alignment : size_t
{
Normal = sizeof(void*),
SSE = 16,
AVX = 32,
};
namespace detail {
void* allocate_aligned_memory(size_t align, size_t size);
void deallocate_aligned_memory(void* ptr) noexcept;
}
template <typename T, Alignment Align = Alignment::AVX>
class AlignedAllocator;
template <Alignment Align>
class AlignedAllocator<void, Align>
{
public:
typedef void* pointer;
typedef const void* const_pointer;
typedef void value_type;
template <class U> struct rebind { typedef AlignedAllocator<U, Align> other; };
};
template <typename T, Alignment Align>
class AlignedAllocator
{
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::true_type propagate_on_container_move_assignment;
template <class U>
struct rebind { typedef AlignedAllocator<U, Align> other; };
public:
AlignedAllocator() noexcept
{}
template <class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept
{}
size_type
max_size() const noexcept
{ return (size_type(~0) - size_type(Align)) / sizeof(T); }
pointer
address(reference x) const noexcept
{ return std::addressof(x); }
const_pointer
address(const_reference x) const noexcept
{ return std::addressof(x); }
pointer
allocate(size_type n, typename AlignedAllocator<void, Align>::const_pointer = 0)
{
const size_type alignment = static_cast<size_type>( Align );
void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void
deallocate(pointer p, size_type) noexcept
{ return detail::deallocate_aligned_memory(p); }
template <class U, class ...Args>
void
construct(U* p, Args&&... args)
{ ::new(reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...); }
void
destroy(pointer p)
{ p->~T(); }
};
template <typename T, Alignment Align>
class AlignedAllocator<const T, Align>
{
public:
typedef T value_type;
typedef const T* pointer;
typedef const T* const_pointer;
typedef const T& reference;
typedef const T& const_reference;
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef std::true_type propagate_on_container_move_assignment;
template <class U>
struct rebind { typedef AlignedAllocator<U, Align> other; };
public:
AlignedAllocator() noexcept
{}
template <class U>
AlignedAllocator(const AlignedAllocator<U, Align>&) noexcept
{}
size_type
max_size() const noexcept
{ return (size_type(~0) - size_type(Align)) / sizeof(T); }
const_pointer
address(const_reference x) const noexcept
{ return std::addressof(x); }
pointer
allocate(size_type n, typename AlignedAllocator<void, Align>::const_pointer = 0)
{
const size_type alignment = static_cast<size_type>( Align );
void* ptr = detail::allocate_aligned_memory(alignment , n * sizeof(T));
if (ptr == nullptr) {
throw std::bad_alloc();
}
return reinterpret_cast<pointer>(ptr);
}
void
deallocate(pointer p, size_type) noexcept
{ return detail::deallocate_aligned_memory(p); }
template <class U, class ...Args>
void
construct(U* p, Args&&... args)
{ ::new(reinterpret_cast<void*>(p)) U(std::forward<Args>(args)...); }
void
destroy(pointer p)
{ p->~T(); }
};
template <typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool
operator== (const AlignedAllocator<T,TAlign>&, const AlignedAllocator<U, UAlign>&) noexcept
{ return TAlign == UAlign; }
template <typename T, Alignment TAlign, typename U, Alignment UAlign>
inline
bool
operator!= (const AlignedAllocator<T,TAlign>&, const AlignedAllocator<U, UAlign>&) noexcept
{ return TAlign != UAlign; }
The implementation for the actual allocate calls is posix only but you can extent that easily.
void*
detail::allocate_aligned_memory(size_t align, size_t size)
{
assert(align >= sizeof(void*));
assert(nail::is_power_of_two(align));
if (size == 0) {
return nullptr;
}
void* ptr = nullptr;
int rc = posix_memalign(&ptr, align, size);
if (rc != 0) {
return nullptr;
}
return ptr;
}
void
detail::deallocate_aligned_memory(void *ptr) noexcept
{
return free(ptr);
}
Needs C++11, btw.
In the upcoming version 1.56, the Boost library will include Boost.Align. Among other memory alignment helpers it provides boost::alignment::aligned_allocator, which can be used a drop-in replacement for std::allocator and allows you to specify an alignment. See the documentation on https://boostorg.github.io/align/
Starting in C++17, just use std::vector<__m256i> or with any other aligned type. There's aligned version of operator new, it is used by std::allocator for aligned types (as well as by plain new-expression, so new __m256i[N] is also safe starting in C++17).
There's a comment by #MarcGlisse saying this, making this an answer to make it more visible.
Yes, it should be possible. If you put this question on google then you will get lots of sample code, below is some promising results:
https://bitbucket.org/marten/alignedallocator/wiki/Home
http://code.google.com/p/mastermind-strategy/source/browse/trunk/src/util/aligned_allocator.hpp?r=167
https://gist.github.com/1471329