1 /*
2  * Copyright (c) 2012-2014 Glen Joseph Fernandes
3  * glenfe at live dot com
4  *
5  * Distributed under the Boost Software License,
6  * Version 1.0. (See accompanying file LICENSE_1_0.txt
7  * or copy at http://boost.org/LICENSE_1_0.txt)
8  */
9 #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
10 #define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP
11 
12 #include <boost/smart_ptr/detail/array_count_impl.hpp>
13 #include <boost/smart_ptr/detail/sp_if_array.hpp>
14 
15 namespace boost {
16     template<class T>
17     inline typename boost::detail::sp_if_array<T>::type
make_shared(std::size_t size)18     make_shared(std::size_t size) {
19         typedef typename boost::detail::array_inner<T>::type T1;
20         typedef typename boost::detail::array_base<T1>::type T2;
21         typedef boost::detail::ms_allocator<T> A1;
22         typedef boost::detail::ms_in_allocator_tag D1;
23         std::size_t n1 = size * boost::detail::array_total<T1>::size;
24         T1* p1 = 0;
25         T2* p2 = 0;
26         D1 d1;
27         A1 a1(size, &p2);
28         shared_ptr<T> s1(p1, d1, a1);
29         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
30         a2->set(0);
31         boost::detail::ms_init(p2, n1);
32         a2->set(p2);
33         p1 = reinterpret_cast<T1*>(p2);
34         return shared_ptr<T>(s1, p1);
35     }
36 
37     template<class T>
38     inline typename boost::detail::sp_if_size_array<T>::type
make_shared()39     make_shared() {
40         typedef typename boost::detail::array_inner<T>::type T1;
41         typedef typename boost::detail::array_base<T1>::type T2;
42         typedef boost::detail::ms_allocator<T> A1;
43         typedef boost::detail::ms_in_allocator_tag D1;
44         enum {
45             N = boost::detail::array_total<T>::size
46         };
47         T1* p1 = 0;
48         T2* p2 = 0;
49         D1 d1;
50         A1 a1(&p2);
51         shared_ptr<T> s1(p1, d1, a1);
52         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
53         a2->set(0);
54         boost::detail::ms_init(p2, N);
55         a2->set(p2);
56         p1 = reinterpret_cast<T1*>(p2);
57         return shared_ptr<T>(s1, p1);
58     }
59 
60     template<class T>
61     inline typename boost::detail::sp_if_array<T>::type
make_shared(std::size_t size,const typename boost::detail::array_inner<T>::type & value)62     make_shared(std::size_t size,
63         const typename boost::detail::array_inner<T>::type& value) {
64         typedef typename boost::detail::array_inner<T>::type T1;
65         typedef typename boost::detail::array_base<T1>::type T2;
66         typedef const T2 T3;
67         typedef boost::detail::ms_allocator<T> A1;
68         typedef boost::detail::ms_in_allocator_tag D1;
69         enum {
70             M = boost::detail::array_total<T1>::size
71         };
72         std::size_t n1 = M * size;
73         T1* p1 = 0;
74         T2* p2 = 0;
75         T3* p3 = reinterpret_cast<T3*>(&value);
76         D1 d1;
77         A1 a1(size, &p2);
78         shared_ptr<T> s1(p1, d1, a1);
79         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
80         a2->set(0);
81         boost::detail::ms_init<T2, M>(p2, n1, p3);
82         a2->set(p2);
83         p1 = reinterpret_cast<T1*>(p2);
84         return shared_ptr<T>(s1, p1);
85     }
86 
87     template<class T>
88     inline typename boost::detail::sp_if_size_array<T>::type
make_shared(const typename boost::detail::array_inner<T>::type & value)89     make_shared(const typename boost::detail::array_inner<T>::type& value) {
90         typedef typename boost::detail::array_inner<T>::type T1;
91         typedef typename boost::detail::array_base<T1>::type T2;
92         typedef const T2 T3;
93         typedef boost::detail::ms_allocator<T> A1;
94         typedef boost::detail::ms_in_allocator_tag D1;
95         enum {
96             M = boost::detail::array_total<T1>::size,
97             N = boost::detail::array_total<T>::size
98         };
99         T1* p1 = 0;
100         T2* p2 = 0;
101         T3* p3 = reinterpret_cast<T3*>(&value);
102         D1 d1;
103         A1 a1(&p2);
104         shared_ptr<T> s1(p1, d1, a1);
105         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
106         a2->set(0);
107         boost::detail::ms_init<T2, M>(p2, N, p3);
108         a2->set(p2);
109         p1 = reinterpret_cast<T1*>(p2);
110         return shared_ptr<T>(s1, p1);
111     }
112 
113     template<class T>
114     inline typename boost::detail::sp_if_array<T>::type
make_shared_noinit(std::size_t size)115     make_shared_noinit(std::size_t size) {
116         typedef typename boost::detail::array_inner<T>::type T1;
117         typedef typename boost::detail::array_base<T1>::type T2;
118         typedef boost::detail::ms_allocator<T> A1;
119         typedef boost::detail::ms_in_allocator_tag D1;
120         std::size_t n1 = size * boost::detail::array_total<T1>::size;
121         T1* p1 = 0;
122         T2* p2 = 0;
123         D1 d1;
124         A1 a1(size, &p2);
125         shared_ptr<T> s1(p1, d1, a1);
126         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
127         a2->set(0);
128         boost::detail::ms_noinit(p2, n1);
129         a2->set(p2);
130         p1 = reinterpret_cast<T1*>(p2);
131         return shared_ptr<T>(s1, p1);
132     }
133 
134     template<class T>
135     inline typename boost::detail::sp_if_size_array<T>::type
make_shared_noinit()136     make_shared_noinit() {
137         typedef typename boost::detail::array_inner<T>::type T1;
138         typedef typename boost::detail::array_base<T1>::type T2;
139         typedef boost::detail::ms_allocator<T> A1;
140         typedef boost::detail::ms_in_allocator_tag D1;
141         enum {
142             N = boost::detail::array_total<T>::size
143         };
144         T1* p1 = 0;
145         T2* p2 = 0;
146         D1 d1;
147         A1 a1(&p2);
148         shared_ptr<T> s1(p1, d1, a1);
149         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
150         a2->set(0);
151         boost::detail::ms_noinit(p2, N);
152         a2->set(p2);
153         p1 = reinterpret_cast<T1*>(p2);
154         return shared_ptr<T>(s1, p1);
155     }
156 }
157 
158 #endif
159