]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* Copyright 2003-2013 Joaquin M Lopez Munoz. |
2 | * Distributed under the Boost Software License, Version 1.0. | |
3 | * (See accompanying file LICENSE_1_0.txt or copy at | |
4 | * http://www.boost.org/LICENSE_1_0.txt) | |
5 | * | |
6 | * See http://www.boost.org/libs/multi_index for library home page. | |
7 | */ | |
8 | ||
9 | #ifndef BOOST_MULTI_INDEX_DETAIL_VARTEMPL_SUPPORT_HPP | |
10 | #define BOOST_MULTI_INDEX_DETAIL_VARTEMPL_SUPPORT_HPP | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | /* Utilities for emulation of variadic template functions. Variadic packs are | |
17 | * replaced by lists of BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS parameters: | |
18 | * | |
19 | * - typename... Args --> BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK | |
20 | * - Args&&... args --> BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK | |
21 | * - std::forward<Args>(args)... --> BOOST_MULTI_INDEX_FORWARD_PARAM_PACK | |
22 | * | |
23 | * Forwarding emulated with Boost.Move. A template functions foo_imp | |
24 | * defined in such way accepts *exactly* BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS | |
25 | * arguments: variable number of arguments is emulated by providing a set of | |
26 | * overloads foo forwarding to foo_impl with | |
27 | * | |
28 | * BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL | |
29 | * BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG (initial extra arg) | |
30 | * | |
31 | * which fill the extra args with boost::multi_index::detail::noarg's. | |
32 | * boost::multi_index::detail::vartempl_placement_new works the opposite | |
33 | * way: it acceps a full a pointer x to Value and a | |
34 | * BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK and forwards to | |
35 | * new(x) Value(args) where args is the argument pack after discarding | |
36 | * noarg's. | |
37 | * | |
38 | * Emulation decays to the real thing when the compiler supports variadic | |
39 | * templates and move semantics natively. | |
40 | */ | |
41 | ||
42 | #include <boost/config.hpp> | |
43 | ||
44 | #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)||\ | |
45 | defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) | |
46 | ||
47 | #include <boost/move/core.hpp> | |
48 | #include <boost/move/utility.hpp> | |
49 | #include <boost/preprocessor/arithmetic/add.hpp> | |
50 | #include <boost/preprocessor/arithmetic/sub.hpp> | |
51 | #include <boost/preprocessor/cat.hpp> | |
52 | #include <boost/preprocessor/control/if.hpp> | |
53 | #include <boost/preprocessor/facilities/empty.hpp> | |
54 | #include <boost/preprocessor/facilities/intercept.hpp> | |
55 | #include <boost/preprocessor/logical/and.hpp> | |
56 | #include <boost/preprocessor/punctuation/comma.hpp> | |
57 | #include <boost/preprocessor/punctuation/comma_if.hpp> | |
58 | #include <boost/preprocessor/repetition/enum.hpp> | |
59 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
60 | #include <boost/preprocessor/repetition/repeat_from_to.hpp> | |
61 | #include <boost/preprocessor/seq/elem.hpp> | |
62 | ||
63 | #if !defined(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS) | |
64 | #define BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS 5 | |
65 | #endif | |
66 | ||
67 | #define BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK \ | |
68 | BOOST_PP_ENUM_PARAMS( \ | |
69 | BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,typename T) | |
70 | ||
71 | #define BOOST_MULTI_INDEX_VARTEMPL_ARG(z,n,_) \ | |
72 | BOOST_FWD_REF(BOOST_PP_CAT(T,n)) BOOST_PP_CAT(t,n) | |
73 | ||
74 | #define BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK \ | |
75 | BOOST_PP_ENUM( \ | |
76 | BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS, \ | |
77 | BOOST_MULTI_INDEX_VARTEMPL_ARG,~) | |
78 | ||
79 | #define BOOST_MULTI_INDEX_VARTEMPL_FORWARD_ARG(z,n,_) \ | |
80 | boost::forward<BOOST_PP_CAT(T,n)>(BOOST_PP_CAT(t,n)) | |
81 | ||
82 | #define BOOST_MULTI_INDEX_FORWARD_PARAM_PACK \ | |
83 | BOOST_PP_ENUM( \ | |
84 | BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS, \ | |
85 | BOOST_MULTI_INDEX_VARTEMPL_FORWARD_ARG,~) | |
86 | ||
87 | namespace boost{namespace multi_index{namespace detail{ | |
88 | struct noarg{}; | |
89 | }}} | |
90 | ||
91 | /* call vartempl function without args */ | |
92 | ||
93 | #define BOOST_MULTI_INDEX_NULL_PARAM_PACK \ | |
94 | BOOST_PP_ENUM_PARAMS( \ | |
95 | BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS, \ | |
96 | boost::multi_index::detail::noarg() BOOST_PP_INTERCEPT) | |
97 | ||
98 | #define BOOST_MULTI_INDEX_TEMPLATE_N(n) \ | |
99 | template<BOOST_PP_ENUM_PARAMS(n,typename T)> | |
100 | ||
101 | #define BOOST_MULTI_INDEX_TEMPLATE_0(n) | |
102 | ||
103 | #define BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_AUX(z,n,data) \ | |
104 | BOOST_PP_IF(n, \ | |
105 | BOOST_MULTI_INDEX_TEMPLATE_N, \ | |
106 | BOOST_MULTI_INDEX_TEMPLATE_0)(n) \ | |
107 | BOOST_PP_SEQ_ELEM(0,data) /* ret */ \ | |
108 | BOOST_PP_SEQ_ELEM(1,data) /* name_from */ ( \ | |
109 | BOOST_PP_ENUM(n,BOOST_MULTI_INDEX_VARTEMPL_ARG,~)) \ | |
110 | { \ | |
111 | return BOOST_PP_SEQ_ELEM(2,data) /* name_to */ ( \ | |
112 | BOOST_PP_ENUM(n,BOOST_MULTI_INDEX_VARTEMPL_FORWARD_ARG,~) \ | |
113 | BOOST_PP_COMMA_IF( \ | |
114 | BOOST_PP_AND( \ | |
115 | n,BOOST_PP_SUB(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,n))) \ | |
116 | BOOST_PP_ENUM_PARAMS( \ | |
117 | BOOST_PP_SUB(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,n), \ | |
118 | boost::multi_index::detail::noarg() BOOST_PP_INTERCEPT) \ | |
119 | ); \ | |
120 | } | |
121 | ||
122 | #define BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL( \ | |
123 | ret,name_from,name_to) \ | |
124 | BOOST_PP_REPEAT_FROM_TO( \ | |
125 | 0,BOOST_PP_ADD(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,1), \ | |
126 | BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_AUX, \ | |
127 | (ret)(name_from)(name_to)) | |
128 | ||
129 | #define BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG_AUX( \ | |
130 | z,n,data) \ | |
131 | BOOST_PP_IF(n, \ | |
132 | BOOST_MULTI_INDEX_TEMPLATE_N, \ | |
133 | BOOST_MULTI_INDEX_TEMPLATE_0)(n) \ | |
134 | BOOST_PP_SEQ_ELEM(0,data) /* ret */ \ | |
135 | BOOST_PP_SEQ_ELEM(1,data) /* name_from */ ( \ | |
136 | BOOST_PP_SEQ_ELEM(3,data) BOOST_PP_SEQ_ELEM(4,data) /* extra arg */\ | |
137 | BOOST_PP_COMMA_IF(n) \ | |
138 | BOOST_PP_ENUM(n,BOOST_MULTI_INDEX_VARTEMPL_ARG,~)) \ | |
139 | { \ | |
140 | return BOOST_PP_SEQ_ELEM(2,data) /* name_to */ ( \ | |
141 | BOOST_PP_SEQ_ELEM(4,data) /* extra_arg_name */ \ | |
142 | BOOST_PP_COMMA_IF(n) \ | |
143 | BOOST_PP_ENUM(n,BOOST_MULTI_INDEX_VARTEMPL_FORWARD_ARG,~) \ | |
144 | BOOST_PP_COMMA_IF( \ | |
145 | BOOST_PP_SUB(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,n)) \ | |
146 | BOOST_PP_ENUM_PARAMS( \ | |
147 | BOOST_PP_SUB(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,n), \ | |
148 | boost::multi_index::detail::noarg() BOOST_PP_INTERCEPT) \ | |
149 | ); \ | |
150 | } | |
151 | ||
152 | #define BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG( \ | |
153 | ret,name_from,name_to,extra_arg_type,extra_arg_name) \ | |
154 | BOOST_PP_REPEAT_FROM_TO( \ | |
155 | 0,BOOST_PP_ADD(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,1), \ | |
156 | BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG_AUX, \ | |
157 | (ret)(name_from)(name_to)(extra_arg_type)(extra_arg_name)) | |
158 | ||
159 | namespace boost{ | |
160 | ||
161 | namespace multi_index{ | |
162 | ||
163 | namespace detail{ | |
164 | ||
165 | #define BOOST_MULTI_INDEX_VARTEMPL_TO_PLACEMENT_NEW_AUX(z,n,name) \ | |
166 | template< \ | |
167 | typename Value \ | |
168 | BOOST_PP_COMMA_IF(n) \ | |
169 | BOOST_PP_ENUM_PARAMS(n,typename T) \ | |
170 | > \ | |
171 | Value* name( \ | |
172 | Value* x \ | |
173 | BOOST_PP_COMMA_IF(n) \ | |
174 | BOOST_PP_ENUM(n,BOOST_MULTI_INDEX_VARTEMPL_ARG,~) \ | |
175 | BOOST_PP_COMMA_IF( \ | |
176 | BOOST_PP_SUB(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,n)) \ | |
177 | BOOST_PP_ENUM_PARAMS( \ | |
178 | BOOST_PP_SUB(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,n), \ | |
179 | BOOST_FWD_REF(noarg) BOOST_PP_INTERCEPT)) \ | |
180 | { \ | |
181 | return new(x) Value( \ | |
182 | BOOST_PP_ENUM(n,BOOST_MULTI_INDEX_VARTEMPL_FORWARD_ARG,~)); \ | |
183 | } | |
184 | ||
185 | #define BOOST_MULTI_INDEX_VARTEMPL_TO_PLACEMENT_NEW(name) \ | |
186 | BOOST_PP_REPEAT_FROM_TO( \ | |
187 | 0,BOOST_PP_ADD(BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,1), \ | |
188 | BOOST_MULTI_INDEX_VARTEMPL_TO_PLACEMENT_NEW_AUX, \ | |
189 | name) | |
190 | ||
191 | BOOST_MULTI_INDEX_VARTEMPL_TO_PLACEMENT_NEW(vartempl_placement_new) | |
192 | ||
193 | #undef BOOST_MULTI_INDEX_VARTEMPL_TO_PLACEMENT_NEW_AUX | |
194 | #undef BOOST_MULTI_INDEX_VARTEMPL_TO_PLACEMENT_NEW | |
195 | ||
196 | } /* namespace multi_index::detail */ | |
197 | ||
198 | } /* namespace multi_index */ | |
199 | ||
200 | } /* namespace boost */ | |
201 | ||
202 | #else | |
203 | ||
204 | /* native variadic templates support */ | |
205 | ||
206 | #include <utility> | |
207 | ||
208 | #define BOOST_MULTI_INDEX_TEMPLATE_PARAM_PACK typename... Args | |
209 | #define BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK Args&&... args | |
210 | #define BOOST_MULTI_INDEX_FORWARD_PARAM_PACK std::forward<Args>(args)... | |
211 | #define BOOST_MULTI_INDEX_NULL_PARAM_PACK | |
212 | ||
213 | #define BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL( \ | |
214 | ret,name_from,name_to) \ | |
215 | template<typename... Args> ret name_from(Args&&... args) \ | |
216 | { \ | |
217 | return name_to(std::forward<Args>(args)...); \ | |
218 | } | |
219 | ||
220 | #define BOOST_MULTI_INDEX_OVERLOADS_TO_VARTEMPL_EXTRA_ARG( \ | |
221 | ret,name_from,name_to,extra_arg_type,extra_arg_name) \ | |
222 | template<typename... Args> ret name_from( \ | |
223 | extra_arg_type extra_arg_name,Args&&... args) \ | |
224 | { \ | |
225 | return name_to(extra_arg_name,std::forward<Args>(args)...); \ | |
226 | } | |
227 | ||
228 | namespace boost{ | |
229 | ||
230 | namespace multi_index{ | |
231 | ||
232 | namespace detail{ | |
233 | ||
234 | template<typename Value,typename... Args> | |
235 | Value* vartempl_placement_new(Value*x,Args&&... args) | |
236 | { | |
237 | return new(x) Value(std::forward<Args>(args)...); | |
238 | } | |
239 | ||
240 | } /* namespace multi_index::detail */ | |
241 | ||
242 | } /* namespace multi_index */ | |
243 | ||
244 | } /* namespace boost */ | |
245 | ||
246 | #endif | |
247 | #endif |