c++-gtk-utils
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 
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::Param::ParamType
const T & ParamType
Definition: param.h:84
Cgu
Definition: application.h:44
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