]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/multi_index/detail/vartempl_support.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / multi_index / detail / vartempl_support.hpp
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