#include <iostream>
using std::cout;
using std::endl;
using std::cerr;

#include <algorithm>
using std::max;

#include <vector>
using std::vector;

#include <list>
using std::list;

#include <cstdlib>

template<typename T>
inline T *allocate( size_t size, T * )
{
    T *result = ( T * )malloc( size * sizeof( T ) );

    if( result == 0 )
    {
        cerr << "Out of memory" << endl;
        exit( EXIT_FAILURE );
    }

    return result;
}

template<typename T>
inline void deallocate( T *buffer )
{
    free( buffer );
}

template<typename T>
class myAllocator
{
    public:
    typedef T           value_type;
    typedef T           *pointer;
    typedef T           &reference;
    typedef const       T *const_pointer;
    typedef const       T &const_reference;
    typedef size_t      size_type;
    typedef ptrdiff_t   difference_type;

    template<typename U>
    struct rebind
    {
        typedef myAllocator<U> other;
    };

    myAllocator()
    {
    }

    myAllocator( const myAllocator & )
    {
    }

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

    ~myAllocator()
    {
    }

    pointer allocate( size_type n )
    {
        //return reinterpret_cast<T *>( Allocate( sizeof( T ) * n ) );
        return ::allocate( n, ( pointer )0 );
    }

    void deallocate( pointer p, size_t /* n */ )
    {
        // Free(p, sizeof(T) * n);
        ::deallocate( p );
    }

    template<typename U>
    void construct( pointer p, const U &value )
    {
        new ( p ) T( value );
    }

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

    pointer address( reference x ) const
    {
        return &x;
    };

    const_pointer address( const_reference x ) const
    {
        return &x;
    }

    size_type max_size() const
    {
        return max( size_type( 1 ), size_type( size_type( -1 ) / sizeof( value_type ) ) );
    }

    bool operator==( const myAllocator & )
    {
        return true;
    }

    bool operator!=( const myAllocator & )
    {
        return false;
    }

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

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

template<>
class myAllocator<void>
{
    public:
    typedef size_t      size_type;
    typedef ptrdiff_t   difference_type;
    typedef void        *pointer;
    typedef const void  *const_pointer;
    typedef void        value_type;

    template<typename U>
    struct rebind
    {
        typedef myAllocator<U>  other;
    };
};

int main()
{
    /* tell STL containers to use our allocator */
    vector< int, myAllocator<int> > v;
    list< int, myAllocator<int> >   l;

    for( int i = 0; i < 50; ++i )
    {
        v.push_back( i + 1 );
        l.push_back( i + 1 );
    }

    for( vector<int>::size_type i = 0; i < 50; ++i )
        cout << ' ' << v[i];

    cout << endl;

    for( list<int>::iterator it = l.begin(); it != l.end(); ++it )
        cout << ' ' << *it;

    cout << endl;

    return 0;
}


