/*
 * Author: Radovan Cerveny
 */

#ifndef STEALTH_ALLOCATOR_HPP_
#define STEALTH_ALLOCATOR_HPP_

#include <memory>
#include <cstddef>
#include "../measurements/MeasurementNew.hpp"

namespace measurements {

template < typename T >
class stealth_allocator {
public:
	using value_type = T;
	using pointer = T *;
	using const_pointer = const T *;
	using reference = T &;
	using const_reference = const T &;
	using size_type = std::size_t;
	using difference_type = std::ptrdiff_t;

	template < typename U >
	struct rebind { using other = stealth_allocator < U >; };

	stealth_allocator ( ) = default;

	template < typename U >
	stealth_allocator ( const stealth_allocator < U > & ) { }

	pointer allocate ( size_type n ) {
		return static_cast < pointer > ( operator new( n * sizeof ( T ), false ) );
	}

	void deallocate ( pointer ptr, size_type ) {
		operator delete( ptr, false );
	}

	void destroy ( pointer p ) {
		p->~T ( );
	}

	template < class ... Args >
	void construct ( pointer p, Args && ... args ) {
		::new ( ( void * ) p )T ( std::forward < Args > ( args ) ... );
	}

};

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

template < typename T, typename U >
bool operator !=( const stealth_allocator < T > &, const stealth_allocator < U > & ) {
	return false;
}

}

#endif /* STEALTH_ALLOCATOR_HPP_ */
