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