make_array_helper.hpp 5.68 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
/*
 * Copyright (c) 2012 Glen Joseph Fernandes 
 * glenfe at live dot com
 *
 * Distributed under the Boost Software License, 
 * Version 1.0. (See accompanying file LICENSE_1_0.txt 
 * or copy at http://boost.org/LICENSE_1_0.txt)
 */
#ifndef BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP
#define BOOST_SMART_PTR_DETAIL_MAKE_ARRAY_HELPER_HPP

#include <boost/type_traits/alignment_of.hpp>

namespace boost {
    namespace detail {
        template<typename T, typename Y = char>
        class make_array_helper;
        template<typename T, typename Y>
        class make_array_helper<T[], Y> {
            template<typename T2, typename Y2>
            friend class make_array_helper;
        public:
            typedef Y           value_type;
            typedef Y*          pointer;
            typedef const Y*    const_pointer;
            typedef Y&          reference;
            typedef const Y&    const_reference;
            typedef std::size_t size_type;
            typedef ptrdiff_t   difference_type;
            template<typename U>
            struct rebind {
                typedef make_array_helper<T[], U> other;
            };
            make_array_helper(std::size_t size, T** data)
                : size(sizeof(T) * size),
                  data(data) {
            }
            template<class U>
            make_array_helper(const make_array_helper<T[], U>& other) 
                : size(other.size),
                  data(other.data) {
            }
            pointer address(reference value) const {
                return &value;
            }
            const_pointer address(const_reference value) const {
                return &value;
            }
            size_type max_size() const {
                return static_cast<std::size_t>(-1) / sizeof(Y);
            }
            pointer allocate(size_type count, const void* = 0) {
                std::size_t a1 = boost::alignment_of<T>::value;
                std::size_t n1 = count * sizeof(Y) + a1 - 1;
                void*  p1 = ::operator new(n1 + size);
                char*  p2 = static_cast<char*>(p1) + n1;
                while (std::size_t(p2) % a1 != 0) {
                    p2--;
                }
                *data = reinterpret_cast<T*>(p2);
                return  reinterpret_cast<Y*>(p1);
            }
            void deallocate(pointer memory, size_type) {
                void* p1 = memory;
                ::operator delete(p1);
            }
            void construct(pointer memory, const Y& value) {
                void* p1 = memory;
                ::new(p1) Y(value);
            }
            void destroy(pointer memory) {
                memory->~Y();
            }
            template<typename U>
            bool operator==(const make_array_helper<T[], U>& other) const {
                return true;
            }
            template<typename U>
            bool operator!=(const make_array_helper<T[], U>& other) const {
                return !(*this == other); 
            }
        private:
            std::size_t size;
            T** data;
        };
        template<typename T, std::size_t N, typename Y>
        class make_array_helper<T[N], Y> {
            template<typename T2, typename Y2>
            friend class make_array_helper;
        public:
            typedef Y           value_type;
            typedef Y*          pointer;
            typedef const Y*    const_pointer;
            typedef Y&          reference;
            typedef const Y&    const_reference;
            typedef std::size_t size_type;
            typedef ptrdiff_t   difference_type;
            template<typename U>
            struct rebind {
                typedef make_array_helper<T[N], U> other;
            };
            make_array_helper(T** data)
                : data(data) {
            }
            template<class U>
            make_array_helper(const make_array_helper<T[N], U>& other) 
                : data(other.data) {
            }
            pointer address(reference value) const {
                return &value;
            }
            const_pointer address(const_reference value) const {
                return &value;
            }
            size_type max_size() const {
                return static_cast<std::size_t>(-1) / sizeof(Y);
            }
            pointer allocate(size_type count, const void* = 0) {
                std::size_t a1 = boost::alignment_of<T>::value;
                std::size_t n1 = count * sizeof(Y) + a1 - 1;
                void*  p1 = ::operator new(n1 + N1);
                char*  p2 = static_cast<char*>(p1) + n1;
                while (std::size_t(p2) % a1 != 0) {
                    p2--;
                }
                *data = reinterpret_cast<T*>(p2);
                return  reinterpret_cast<Y*>(p1);
            }
            void deallocate(pointer memory, size_type) {
                void* p1 = memory;
                ::operator delete(p1);
            }
            void construct(pointer memory, const Y& value) {
                void* p1 = memory;
                ::new(p1) Y(value);
            }
            void destroy(pointer memory) {
                memory->~Y();
            }
            template<typename U>
            bool operator==(const make_array_helper<T[N], U>& other) const {
                return true;
            }
            template<typename U>
            bool operator!=(const make_array_helper<T[N], U>& other) const {
                return !(*this == other); 
            }
        private:
            enum {
                N1 = N * sizeof(T)
            };
            T** data;
        };
    }
}

#endif