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 \
68BOOST_PP_ENUM_PARAMS( \
69 BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS,typename T)
70
71#define BOOST_MULTI_INDEX_VARTEMPL_ARG(z,n,_) \
72BOOST_FWD_REF(BOOST_PP_CAT(T,n)) BOOST_PP_CAT(t,n)
73
74#define BOOST_MULTI_INDEX_FUNCTION_PARAM_PACK \
75BOOST_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,_) \
80boost::forward<BOOST_PP_CAT(T,n)>(BOOST_PP_CAT(t,n))
81
82#define BOOST_MULTI_INDEX_FORWARD_PARAM_PACK \
83BOOST_PP_ENUM( \
84 BOOST_MULTI_INDEX_LIMIT_VARTEMPL_ARGS, \
85 BOOST_MULTI_INDEX_VARTEMPL_FORWARD_ARG,~)
86
87namespace boost{namespace multi_index{namespace detail{
88struct noarg{};
89}}}
90
91/* call vartempl function without args */
92
93#define BOOST_MULTI_INDEX_NULL_PARAM_PACK \
94BOOST_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) \
99template<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) \
104BOOST_PP_IF(n, \
105 BOOST_MULTI_INDEX_TEMPLATE_N, \
106 BOOST_MULTI_INDEX_TEMPLATE_0)(n) \
107BOOST_PP_SEQ_ELEM(0,data) /* ret */ \
108BOOST_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) \
124BOOST_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) \
131BOOST_PP_IF(n, \
132 BOOST_MULTI_INDEX_TEMPLATE_N, \
133 BOOST_MULTI_INDEX_TEMPLATE_0)(n) \
134BOOST_PP_SEQ_ELEM(0,data) /* ret */ \
135BOOST_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) \
154BOOST_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
159namespace boost{
160
161namespace multi_index{
162
163namespace detail{
164
165#define BOOST_MULTI_INDEX_VARTEMPL_TO_PLACEMENT_NEW_AUX(z,n,name) \
166template< \
167 typename Value \
168 BOOST_PP_COMMA_IF(n) \
169 BOOST_PP_ENUM_PARAMS(n,typename T) \
170> \
171Value* 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) \
186BOOST_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
191BOOST_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) \
215template<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) \
222template<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
228namespace boost{
229
230namespace multi_index{
231
232namespace detail{
233
234template<typename Value,typename... Args>
235Value* 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
248