#include <iostream>
#include <vector>
#include <typeinfo>
#include <utility>
#include <string>
template<class T, int N>
class stack_allocator {
public:
typedef T value_type;
using propagate_on_container_copy_assignment = std::true_type; // The copy needs to have its
// own allocator.
using propagate_on_container_move_assignment = std::true_type; // to avoid the pessimization
using propagate_on_container_swap = std::true_type; // to avoid the undefined behavior
stack_allocator() : m_is_allocated1(false) {}
stack_allocator(const stack_allocator<T, N> &other) {
m_is_allocated1 = false;
std::cout << "Copy" <<std::endl;
}
stack_allocator<T, N> &operator=(const stack_allocator<T, N> &other) {
m_is_allocated1 = false;
std::cout << "Copy assignment" <<std::endl;
return *this;
}
auto select_on_container_copy_construction() const {
return stack_allocator<T, N>();
}
T *allocate(const std::size_t size) {
if(!m_is_allocated1) {
m_is_allocated1 = true;
std::cout << "Allocate: " << reinterpret_cast<T*>(m_preallocated1) << std::endl;
return reinterpret_cast<T*>(m_preallocated1);
}
else {
throw std::bad_alloc();
}
}
void deallocate(T * ptr, const std::size_t size) {
if(ptr == reinterpret_cast<T*>(m_preallocated1) && m_is_allocated1) {
m_is_allocated1 = false;
std::cout << "DEALLOC1: " << ptr << std::endl;
}
else {
std::cout << "DEALLOC ILLEGAL PTR: " << ptr << " : " << reinterpret_cast<T*>(m_preallocated1) << std::endl;
throw std::bad_alloc();
}
}
std::size_t max_size() const {
return N;
}
template<class U>
struct rebind { using other = stack_allocator<U, N>; };
template< class T1, int N1, class T2, int N2>
friend bool operator==(const stack_allocator<T1, N1> & lhs,
const stack_allocator<T2, N2> & rhs ) noexcept;
template< class T1, int N1, class T2, int N2>
friend bool operator!=(const stack_allocator<T1, N1> & lhs,
const stack_allocator<T2, N2> & rhs ) noexcept;
private:
bool m_is_allocated1;
// properly aligned uninitialized storage for N T's
typename std::aligned_storage<sizeof(T), alignof(T)>::type m_preallocated1[N];
};
template< class T1, int N1, class T2, int N2>
bool operator==(const stack_allocator<T1, N1> & lhs,
const stack_allocator<T2, N2> & rhs ) noexcept {
std::cout << "Compare Equal" << std::endl;
return lhs.m_preallocated1 == rhs.m_preallocated1;
}
template< class T1, int N1, class T2, int N2>
bool operator!=(const stack_allocator<T1, N1> & lhs,
const stack_allocator<T2, N2> & rhs ) noexcept {
std::cout << "Compare Not Equal" << std::endl;
return lhs.m_preallocated1 != rhs.m_preallocated1;
}
template<class T, int N>
using stack_vector = std::vector<T, stack_allocator<T, N>>;
int main() {
stack_allocator<int, 5> sa;
stack_allocator<int, 5> sb;
if(sa == sb) {
std::cout << "EQUAL" << std::endl;
}
if(sa != sb) {
std::cout << "NOT EQUAL" << std::endl;
}
stack_vector<int, 5> vv;
vv.reserve(1);
vv.shrink_to_fit();
}