c++-gtk-utils

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

param.h
Go to the documentation of this file.
1 /* Copyright (C) 2010, 2011 and 2014 Chris Vine
2
3 The library comprised in this file or of which this file is part is
4 distributed by Chris Vine under the GNU Lesser General Public
5 License as follows:
6
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public License
9 as published by the Free Software Foundation; either version 2.1 of
10 the License, or (at your option) any later version.
11
12 This library is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License, version 2.1, for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License, version 2.1, along with this library (see the file LGPL.TXT
19 which came with this source code package in the c++-gtk-utils
20 sub-directory); if not, write to the Free Software Foundation, Inc.,
21 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 However, it is not intended that the object code of a program whose
24 source code instantiates a template from this file or uses macros or
25 inline functions (of any length) should by reason only of that
26 instantiation or use be subject to the restrictions of use in the GNU
27 Lesser General Public License. With that in mind, the words "and
28 macros, inline functions and instantiations of templates (of any
29 length)" shall be treated as substituted for the words "and small
30 macros and small inline functions (ten lines or less in length)" in
31 the fourth paragraph of section 5 of that licence. This does not
32 affect any other reason why object code may be subject to the
33 restrictions in that licence (nor for the avoidance of doubt does it
34 affect the application of section 2 of that licence to modifications
35 of the source code in this file).
36
37 */
38
39 #ifndef CGU_PARAM_H
40 #define CGU_PARAM_H
41
42 #include <c++-gtk-utils/cgu_config.h>
43
44 #ifdef CGU_USE_TUPLE
45 #include <tuple>
46 #include <cstddef> // for std::size_t
47 #include <utility> // for std::forward and std::move
48 #include <type_traits> // for std::result_of
49 #endif
50
51 namespace Cgu {
52
53 /**
54 * @class Param param.h c++-gtk-utils/param.h
55 * @brief Struct for automatic typing of function parameter arguments
56 *
57 * @details This struct uses template partial specialisation in order
58 * to provide automatic type mapping for function arguments. It is
59 * used by the unbound arguments of callback objects and their related
60 * functors and emitter objects. (A more detailed explanation is that
61 * it is used where a virtual function is at the end of a call chain,
62 * notably the dispatch() method of callback objects, with the result
63 * that we cannot templatise the virtual function itself in order to
64 * use std::forward for argument passing, but instead have to type-map
65 * the arguments using class templates.)
66 *
67 * Mapping is as follows:
68 *
69 * A value argument is mapped to reference to const of the value
70 * type.
71 *
72 * A pointer argument is mapped to pointer argument (its original
73 * type).
74 *
75 * A non-const reference argument is mapped to non-const reference
76 * (its original type).
77 *
78 * A const reference argument is mapped to const reference (its
79 * original type).
80 */
81
82 template<class T>
83 struct Param {
84 typedef const T& ParamType;
85 };
86
87 template<class T>
88 struct Param<T&> {
89 typedef T& ParamType;
90 };
91
92 template<class T>
93 struct Param<T*> {
94 typedef T* ParamType;
95 };
96
97 /**
98 * @class RemoveRefCond param.h c++-gtk-utils/param.h
99 * @brief Struct which will conditionally convert a reference type to
100 * a value type
101 *
102 * @details This struct is used by Callback::make() and
103 * Callback::make_ref() where the std::tuple backend is not used to
104 * implement the callback classes, so that where a call is made to
105 * Callback::make_ref() and the target function's arguments include
106 * one with a reference, that reference is removed.
107 *
108 * Since 2.0.0-rc3
109 */
110 template<class T, bool unref>
111 struct RemoveRefCond {};
112
113 template<class T>
114 struct RemoveRefCond<T, true> {
115 typedef T Type;
116 };
117
118 template<class T>
119 struct RemoveRefCond<T&, true> {
120 typedef T Type;
121 };
122
123 template<class T>
124 struct RemoveRefCond<T, false> {
125 typedef T Type;
126 };
127
128 // explicatory only - we could do without this specialisation
129 template<class T>
130 struct RemoveRefCond<T&, false> {
131 typedef T& Type;
132 };
133
134 // the remainder of this file implements tuple_apply()
135
136 #if defined(DOXYGEN_PARSING) || defined(CGU_USE_TUPLE)
137
138 #ifndef DOXYGEN_PARSING
139
140 namespace TupleHelper {
141
142 /*
143 MakeIndexList provides a list of tuple indices for any given
144 instantiation, comprised in the type of an IndexList object. For
145 example, MakeIndexList<4>::Type is of type IndexList<0, 1, 2, 3>.
146 The index values held in the type of the IndexList object are then
147 unpacked into std::get().
148
149 IndexList is the base class for MakeIndexList, from which the
150 complete MakeIndexList instantiation ending recursion derives in
151 order to deliver up the index list for tuple_apply_impl - its Type
152 member is itself. So the inheritance diagram for MakeIndexList<4>
153 is:
154
155 IndexList<0, 1, 2, 3>
156 |
157 |
158 MakeIndexList<0, 0, 1, 2, 3>
159 |
160 |
161 MakeIndexList<1, 1, 2, 3>
162 |
163 |
164 MakeIndexList<2, 2, 3>
165 |
166 |
167 MakeIndexList<3, 3>
168 |
169 |
170 MakeIndexList<4>
171 */
172
173 template<std::size_t... indices>
174 struct IndexList {
175 typedef IndexList<indices...> Type;
176 };
177
178 template<std::size_t count, std::size_t... indices>
179 struct MakeIndexList: public MakeIndexList<count - 1, count - 1, indices...> {};
180
181 // ends recursion - the complete (one from base) class, inheriting
182 // directly from IndexList
183 template<std::size_t... indices>
184 struct MakeIndexList<0, indices...>: public IndexList<indices...> {};
185
186 template <class Obj, class Ret, class... FuncArgs, class Tuple,
187 std::size_t... indices, class... OtherArgs>
188 Ret tuple_apply_impl(Obj& obj,
189 Ret (Obj::* func) (FuncArgs...),
190 Tuple&& t,
191 IndexList<indices...>,
192 OtherArgs&&... args) {
193 return (obj.*func)(std::get<indices>(std::forward<Tuple>(t))..., std::forward<OtherArgs>(args)...);
194 }
195
196 template <class Obj, class Ret, class... FuncArgs, class Tuple,
197 std::size_t... indices, class... OtherArgs>
198 Ret tuple_apply_impl(const Obj& obj,
199 Ret (Obj::* func) (FuncArgs...) const,
200 Tuple&& t,
201 IndexList<indices...>,
202 OtherArgs&&... args) {
203 return (obj.*func)(std::get<indices>(std::forward<Tuple>(t))..., std::forward<OtherArgs>(args)...);
204 }
205
206 template <class Ret, class Func, class Tuple,
207 std::size_t... indices, class... OtherArgs>
208 Ret tuple_apply_impl(Func&& func,
209 Tuple&& t,
210 IndexList<indices...>,
211 OtherArgs&&... args) {
212 return func(std::get<indices>(std::forward<Tuple>(t))..., std::forward<OtherArgs>(args)...);
213 }
214
215 } // namespace TupleHelper
216
217 #endif // DOXYGEN_PARSING
218
219 /**
220 * @defgroup tuple tuple
221 *
222 * \#include <c++-gtk-utils/param.h>
223 *
224 * From version 2.2.10, where this library is compiled with gcc >= 4.8
225 * or clang >= 3.4, the library uses a backend for relevant
226 * closure/callback classes using std::tuple (unless that backend is
227 * explicitly disabled with the \--without-tuple configuration option,
228 * in which case the implementation used prior to version 2.2.10 is
229 * retained). The tuple backend avoids code duplication and makes for
230 * a cleaner implementation, and enables Callback::make() and
231 * Callback::make_ref() to take up to 10 bound arguments instead of
232 * the previous 5 bound arguments. For compilers other than gcc and
233 * clang which adequately support std::tuple, the tuple backend can be
234 * manually selected with the \--with-tuple configuration option.
235 * Both backends are ABI compatible, because for closure/callback
236 * implementation this library only exports the CallbackArg pure
237 * virtual class.
238 *
239 * Where this library has been compiled with the tuple backend for
240 * callback classes, it uses the Cgu::tuple_apply() utility function
241 * to expand tuples into their component elements in order to pass
242 * those elements to functions as arguments on function calls.
243 * Because this utility function is of general use, it is made
244 * available by the library more generally in the param.h header.
245 *
246 * Taking a function with the signature 'int my_func(int, double, int,
247 * double)', a tuple could be expanded to apply the my_func() function
248 * to it as follows:
249 *
250 * @code
251 * int my_func(int, double, int, double);
252 * auto tup = make_tuple(2, 3.0, 4, 5.0);
253 * int res = Cgu::tuple_apply(my_func, tup);
254 * @endcode
255 *
256 * Trailing arguments not comprising part of the tuple can also be
257 * passed to the function, so in the above example my_func() could be
258 * called as follows:
259 *
260 * @code
261 * int my_func(int, double, int, double);
262 * auto tup = make_tuple(2, 3.0);
263 * int res = Cgu::tuple_apply(my_func, tup, 4, 5.0);
264 * @endcode
265 *
266 * Overloads of the tuple_apply() function are provided which can
267 * apply any callable object (including a normal function, a static
268 * member function, the return value of std::bind() or a lambda
269 * expression) to a tuple, or which can apply a const or non-const
270 * non-static member function with object to the tuple.
271 */
272
273 // We need three overloads of the version of this function which takes
274 // a callable object (two for tuple lvalues and one for tuple rvalues)
275 // because we cannot have the tuple as a completely deduced type in
276 // this context - we need to deduce TupleArgs for std::result_of.
277 // These overloads will work with any callable object, including a
278 // function pointer.
279 /**
280 * \#include <c++-gtk-utils/param.h>
281 *
282 * This function expands a tuple and uses the tuple's elements as
283 * arguments to a call to a callable object, such as a normal
284 * function, a static member function, the return value of std::bind()
285 * or a lambda expression.
286 *
287 * @param func The callable object.
288 * @param t The std::tuple object to be expanded.
289 * @param args The trailing arguments (if any) to be used in the
290 * function call.
291 * @return The result of applying func to the tuple and any trailing
292 * arguments.
293 * @note This function is not available unless either (i) this library
294 * is compiled with gcc >= 4.8 or clang >= 3.4, or (ii) the library is
295 * compiled by another compiler with appropriate support for C++11
296 * tuples using the \--with-tuple configuration option.
297 *
298 * Since 2.2.10
299 * @ingroup tuple
300 */
301 template<class Func,
302 class... TupleArgs,
303 class... OtherArgs>
304 auto tuple_apply(Func&& func,
305 const std::tuple<TupleArgs...>& t,
306 OtherArgs&&... args) -> typename std::result_of<Func(const TupleArgs&..., OtherArgs&&...)>::type {
307 typedef typename std::result_of<Func(const TupleArgs&..., OtherArgs&&...)>::type Ret;
308 typedef typename TupleHelper::MakeIndexList<sizeof...(TupleArgs)>::Type List;
309 return TupleHelper::tuple_apply_impl<Ret>(std::forward<Func>(func),
310 t,
311 List(),
312 std::forward<OtherArgs>(args)...);
313 }
314
315 /**
316 * \#include <c++-gtk-utils/param.h>
317 *
318 * This function expands a tuple and uses the tuple's elements as
319 * arguments to a call to a callable object, such as a normal
320 * function, a static member function, the return value of std::bind()
321 * or a lambda expression.
322 *
323 * @param func The callable object.
324 * @param t The std::tuple object to be expanded.
325 * @param args The trailing arguments (if any) to be used in the
326 * function call.
327 * @return The result of applying func to the tuple and any trailing
328 * arguments.
329 * @note This function is not available unless either (i) this library
330 * is compiled with gcc >= 4.8 or clang >= 3.4, or (ii) the library is
331 * compiled by another compiler with appropriate support for C++11
332 * tuples using the \--with-tuple configuration option.
333 *
334 * Since 2.2.10
335 * @ingroup tuple
336 */
337 template<class Func,
338 class... TupleArgs,
339 class... OtherArgs>
340 auto tuple_apply(Func&& func,
341 std::tuple<TupleArgs...>& t,
342 OtherArgs&&... args) -> typename std::result_of<Func(TupleArgs&..., OtherArgs&&...)>::type {
343 typedef typename std::result_of<Func(TupleArgs&..., OtherArgs&&...)>::type Ret;
344 typedef typename TupleHelper::MakeIndexList<sizeof...(TupleArgs)>::Type List;
345 return TupleHelper::tuple_apply_impl<Ret>(std::forward<Func>(func),
346 t,
347 List(),
348 std::forward<OtherArgs>(args)...);
349 }
350
351 /**
352 * \#include <c++-gtk-utils/param.h>
353 *
354 * This function expands a tuple and uses the tuple's elements as
355 * arguments to a call to a callable object, such as a normal
356 * function, a static member function, the return value of std::bind()
357 * or a lambda expression.
358 *
359 * @param func The callable object.
360 * @param t The std::tuple object to be expanded.
361 * @param args The trailing arguments (if any) to be used in the
362 * function call.
363 * @return The result of applying func to the tuple and any trailing
364 * arguments.
365 * @note This function is not available unless either (i) this library
366 * is compiled with gcc >= 4.8 or clang >= 3.4, or (ii) the library is
367 * compiled by another compiler with appropriate support for C++11
368 * tuples using the \--with-tuple configuration option.
369 *
370 * Since 2.2.10
371 * @ingroup tuple
372 */
373 template<class Func,
374 class... TupleArgs,
375 class... OtherArgs>
376 auto tuple_apply(Func&& func,
377 std::tuple<TupleArgs...>&& t,
378 OtherArgs&&... args) -> typename std::result_of<Func(TupleArgs&&..., OtherArgs&&...)>::type {
379 typedef typename std::result_of<Func(TupleArgs&&..., OtherArgs&&...)>::type Ret;
380 typedef typename TupleHelper::MakeIndexList<sizeof...(TupleArgs)>::Type List;
381 return TupleHelper::tuple_apply_impl<Ret>(std::forward<Func>(func),
382 std::move(t),
383 List(),
384 std::forward<OtherArgs>(args)...);
385 }
386
387 /**
388 * \#include <c++-gtk-utils/param.h>
389 *
390 * This function expands a tuple and uses the tuple's elements as
391 * arguments to a function call to a non-static class member function.
392 *
393 * @param obj The object whose member function is to be called.
394 * @param func The non-static member function to be called.
395 * @param t The std::tuple object to be expanded.
396 * @param args The trailing arguments (if any) to be used in the
397 * function call.
398 * @return The result of applying func to the tuple and any trailing
399 * arguments.
400 * @note This function is not available unless either (i) this library
401 * is compiled with gcc >= 4.8 or clang >= 3.4, or (ii) the library is
402 * compiled by another compiler with appropriate support for C++11
403 * tuples using the \--with-tuple configuration option.
404 *
405 * Since 2.2.10
406 * @ingroup tuple
407 */
408 template<class Obj, class Ret, class... FuncArgs, class Tuple, class... OtherArgs>
409 Ret tuple_apply(Obj& obj,
410 Ret (Obj::* func) (FuncArgs...),
411 Tuple&& t,
412 OtherArgs&&... args) {
413 typedef typename std::remove_reference<Tuple>::type TupleType;
414 static_assert(sizeof...(FuncArgs) == std::tuple_size<TupleType>::value + sizeof...(OtherArgs),
415 "The arity of the function passed to tuple_apply() and the "
416 "arguments passed to it do not match");
417 typedef typename TupleHelper::MakeIndexList<std::tuple_size<TupleType>::value>::Type List;
418 return TupleHelper::tuple_apply_impl(obj,
419 func,
420 std::forward<Tuple>(t),
421 List(),
422 std::forward<OtherArgs>(args)...);
423 }
424
425 /**
426 * \#include <c++-gtk-utils/param.h>
427 *
428 * This function expands a tuple and uses the tuple's elements as
429 * arguments to a function call to a non-static class member function.
430 *
431 * @param obj The object whose member function is to be called.
432 * @param func The non-static member function to be called.
433 * @param t The std::tuple object to be expanded.
434 * @param args The trailing arguments (if any) to be used in the
435 * function call.
436 * @return The result of applying func to the tuple and any trailing
437 * arguments.
438 * @note This function is not available unless either (i) this library
439 * is compiled with gcc >= 4.8 or clang >= 3.4, or (ii) the library is
440 * compiled by another compiler with appropriate support for C++11
441 * tuples using the \--with-tuple configuration option.
442 *
443 * Since 2.2.10
444 * @ingroup tuple
445 */
446 template<class Obj, class Ret, class... FuncArgs, class Tuple, class... OtherArgs>
447 Ret tuple_apply(const Obj& obj,
448 Ret (Obj::* func) (FuncArgs...) const,
449 Tuple&& t,
450 OtherArgs&&... args) {
451 typedef typename std::remove_reference<Tuple>::type TupleType;
452 static_assert(sizeof...(FuncArgs) == std::tuple_size<TupleType>::value + sizeof...(OtherArgs),
453 "The arity of the function passed to tuple_apply() and the "
454 "arguments passed to it do not match");
455 typedef typename TupleHelper::MakeIndexList<std::tuple_size<TupleType>::value>::Type List;
456 return TupleHelper::tuple_apply_impl(obj,
457 func,
458 std::forward<Tuple>(t),
459 List(),
460 std::forward<OtherArgs>(args)...);
461 }
462
463 #endif // CGU_USE_TUPLE
464
465 } // namespace Cgu
466
467 #endif // CGU_PARAM_H
Cgu::Param
Struct for automatic typing of function parameter arguments.
Definition: param.h:83
Cgu::Param< T & >::ParamType
T & ParamType
Definition: param.h:89
Cgu
Definition: application.h:44
Cgu::Param::ParamType
const typedef T & ParamType
Definition: param.h:84
Cgu::RemoveRefCond< T, false >::Type
T Type
Definition: param.h:125
Cgu::RemoveRefCond
Struct which will conditionally convert a reference type to a value type.
Definition: param.h:111
Cgu::Param< T * >::ParamType
T * ParamType
Definition: param.h:94
Cgu::tuple_apply
auto tuple_apply(Func &&func, const std::tuple< TupleArgs... > &t, OtherArgs &&... args) -> typename std::result_of< Func(const TupleArgs &..., OtherArgs &&...)>::type
Definition: param.h:304
Cgu::RemoveRefCond< T &, false >::Type
T & Type
Definition: param.h:131
Cgu::RemoveRefCond< T &, true >::Type
T Type
Definition: param.h:120
Cgu::RemoveRefCond< T, true >::Type
T Type
Definition: param.h:115
cgu_config.h