c++-gtk-utils
do_if.h
Go to the documentation of this file.
1 /* Copyright (C) 2010 and 2011 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_DO_IF_H
40 #define CGU_DO_IF_H
41 
42 /**
43  * @file do_if.h
44  * @brief This file provides utility functions for conditional compilation.
45  *
46  * \#include <c++-gtk-utils/do_if.h>
47  *
48  * The DoIf namespace of the library provides a small subset of
49  * template meta-programming techniques likely to be most relevant to
50  * GUI programming (if something more substantial is required,
51  * something like boost or loki should be used).
52  *
53  * For conditional compilation, the library provides the
54  * Cgu::DoIf::mem_fun() utility functions which will conditionally
55  * compile a call to a non-static class member function if, and only
56  * if, the target object has that function as a member. If it does
57  * not have the member function as a member, the call will just do
58  * nothing rather than generate a compiler error, as it will also if
59  * the target object is const and the member function to be called is
60  * non-const. In addition Cgu::DoIf::fun() will conditionally compile
61  * a call to an ordinary function (or static member function) if, and
62  * only if, the target object is convertible to the type (say, a base
63  * type) held by pointer as the first argument of that function.
64  *
65  * They therefore provide compile-time inheritance checking based on
66  * the static type of the object passed to them. They save dynamic
67  * casting (and therefore run time overhead and the requirement for
68  * target types to have a virtual method) in templated functions when
69  * the static type is all that is necessary to enable type checking to
70  * be carried out.
71  *
72  * This is not just a template curiosity, but enables more generic
73  * programming practices when, say, passing mixins to templated
74  * functions. A templated function can be passed an object as a
75  * template type, and that function can then conditionally call member
76  * functions of objects passed to it. If the object has a particular
77  * function as a member, Cgu::DoIf::mem_fun() will call the function,
78  * and if not it will do nothing without causing a compilation error.
79  * It can be particularly useful for templated set-up or tear-down
80  * functions intended to take a wide variety of different objects with
81  * differing features.
82  *
83  * As mentioned above, Cgu::DoIf::mem_fun() and Cgu::DoIf::fun() will
84  * do nothing if an attempt is made to execute a non-const function on
85  * a const object, as well as if the object type does not match the
86  * function or member function sought to be invoked. If a compilation
87  * failure is wanted in a case of const mismatch instead of doing
88  * nothing, from version 2.0.1 the static assertion
89  * Cgu::DoIf::assert_not_const() can be invoked before the call to a
90  * non-const function is made by Cgu::DoIf::mem_fun() or
91  * Cgu::DoIf::fun().
92  *
93  * @b Non-static @b member @b functions
94  *
95  * The first argument to be passed to Cgu::DoIf::mem_fun() is the
96  * target object to be tested and the second argument is the
97  * non-static member function which is to be called with respect to
98  * that object if it has the function as a member. Any number of
99  * further arguments can be passed, representing the arguments to be
100  * provided to that member function. These further arguments may be
101  * reference arguments (const or non-const), value arguments or
102  * r-values, and for automatic pass-through they are passed by r-value
103  * reference and std::forward(), so no overhead should be created if
104  * value or r-value arguments are passed via Cgu::DoIf::mem_fun().
105  *
106  * As an example, take a class which uses multiple inheritance to
107  * inherit from Cgu::EmitterArg as a mixin (normally a class would
108  * have an Emitter object as a member, but it can be inherited from).
109  * A container of objects could have the emit() method called on them
110  * in a case where they do inherit from EmitterArg, where the code
111  * does nothing if they do not. For example:
112  * @code
113  * class Calc {
114  * public:
115  * void do_calc(void);
116  * };
117  *
118  * class CalcEmit: public Calc,
119  * public Cgu::EmitterArg<int> {
120  * };
121  *
122  * ... some code blocks elsewhere ...
123  *
124  * template <class T>
125  * void dispatch_calcs(const std::vector<T>& v) {
126  * int count;
127  * typename std::vector<T>::const_iterator iter;
128  * for (count = 0, iter = v.begin();
129  * iter != v.end();
130  * ++count, ++iter) {
131  * iter->do_calc();
132  * Cgu::DoIf::mem_fun(*iter, // object to be tested
133  * &Cgu::EmitterArg<int>::emit, // member function to be conditionally called
134  * count); // argument
135  * }
136  * }
137  * @endcode
138  *
139  * @b Ordinary @b functions @b and @b static @b member @b functions
140  *
141  * The use of Cgu::DoIf::fun() with normal functions and static member
142  * functions is similar to the use of mem_fun() with non-static member
143  * functions, except that the first argument of the function to be
144  * conditionally called must be a pointer to a type to which the
145  * target object can prospectively be converted. The first argument
146  * to be passed to Cgu::DoIf::fun() is the target object to be tested
147  * and the second argument is the function which is to be
148  * conditionally called if the conversion can be accomplished. If the
149  * function to be conditionally called is so called, the target object
150  * will be passed by pointer to it. Any number of further arguments
151  * can be passed to Cgu::DoIf::fun(), representing additional
152  * arguments to be provided to the function to be conditionally
153  * called, which may be reference arguments, value arguments or
154  * r-value reference arguments (and automatic pass-through is
155  * provided, as in the case of mem_fun()).
156  *
157  * The use of Cgu::DoIf::fun() with ordinary functions can be useful
158  * for batching a number of calls to be made to a test object. For
159  * example:
160  *
161  * @code
162  * class Calc {
163  * public:
164  * void do_calc();
165  * };
166  *
167  * class CalcEmit: public Calc,
168  * public Cgu::EmitterArg<int> {
169  * public:
170  * void clean_up(int);
171  * };
172  *
173  * ... some code blocks elsewhere ...
174  *
175  * void emit_on_calcs(CalcEmit* c, int count) {
176  * c->emit(count);
177  * c->clean_up(count);
178  * }
179  *
180  * template <class T>
181  * void dispatch_calcs(const std::vector<T>& v) {
182  * int count;
183  * typename std::vector<T>::const_iterator iter;
184  * for (count = 0, iter = v.begin();
185  * iter != v.end();
186  * ++count, ++iter) {
187  * iter->do_calc();
188  * Cgu::DoIf::fun(*iter, // object to be tested against first argument of function to be conditionally called
189  * &emit_on_calcs, // function to be conditionally called
190  * count); // second argument of function to be conditionally called
191  * }
192  * }
193  * @endcode
194  *
195  * @b Return @b values
196  *
197  * If the function to be called returns something other than void and
198  * the function to be conditionally called is not called, then
199  * mem_fun() and fun() pass back a dummy object of the return type
200  * using that type's default constructor. The returned object has no
201  * meaning beyond that in such a case, so it should not be relied on
202  * as holding anything other than its default value on default
203  * construction in a case of failure. This in turn means that any
204  * return value, if not a built-in type, must have a default
205  * constructor.
206  *
207  * @b Overloaded @b functions
208  *
209  * Where a referenced member function or ordinary function is
210  * overloaded, this will cause difficulties in template type deduction
211  * when mem_fun() or fun() is called, requiring explicit
212  * disambiguation. For example the following will fail to compile
213  * unless explicitly disambiguated:
214  * @code
215  * class A {
216  * public:
217  * void do_it(int i);
218  * void do_it(int i, int j);
219  * void do_it(double d);
220  * };
221  * int func(A* a, int i);
222  * int func(A* a, double d);
223  *
224  * template <class T>
225  * void do_it_if(T& t) {
226  * int i = 1, j = 2;
227  * double d = 10.0;
228  * Cgu::DoIf::mem_fun(t, &A::do_it, i); // won't compile
229  * Cgu::DoIf::mem_fun(t, &A::do_it, i, j); // won't compile
230  * Cgu::DoIf::mem_fun(t, &A::do_it, d); // won't compile
231  * Cgu::DoIf::fun(t, func, i); // won't compile
232  * Cgu::DoIf::fun(t, func, d); // won't compile
233  *
234  * Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int)>(&A::do_it), i); // OK
235  * Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int, int)>(&A::do_it), i, j); // OK
236  * Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(double)>(&A::do_it), d); // OK
237  * Cgu::DoIf::fun(t, static_cast<int (*)(A*, int)>(func), i); // OK
238  * Cgu::DoIf::fun(t, static_cast<int (*)(A*, double)>(func), d); // OK
239  * }
240  * @endcode
241  *
242  * @b Static @b assertion
243  *
244  * This library also provides the Cgu::DoIf::assert_related_to_type(),
245  * Cgu::DoIf::assert_related_types() and Cgu::DoIf::assert_same_type()
246  * static type-checking assertions. If the matters asserted are not
247  * true, a compile time error in the line where the functions are
248  * instantiated will occur.
249  *
250  * These static assertion functions can be viewed as doing the
251  * opposite of Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(). The
252  * mem_fun() and fun() functions will make a conditional call, and do
253  * nothing if the test condition is not met without a compile time or
254  * run time error, in order to provide compile time polymorphism. On
255  * the other hand, assert_related_to_type(), assert_related_types()
256  * and assert_same_type() cause an explicit compilation error where
257  * the test condition is not met at an ascertainable point in the code
258  * whilst avoiding a slew of incomprehensible error messages from the
259  * compiler. They enable compile time checking of type related
260  * invariants.
261  *
262  * In addition, from version 2.0.1, a Cgu::DoIf::assert_not_const()
263  * static assertion is available.
264  *
265  * The static assertions add nothing to the compiled object code.
266  * They either succeed or fail at compile time.
267  */
268 
269 /**
270  * @namespace Cgu::DoIf
271  * @brief This namespace provides utility functions for conditional compilation.
272  *
273  * \#include <c++-gtk-utils/do_if.h>
274  *
275  * The DoIf namespace of the library provides a small subset of
276  * template meta-programming techniques likely to be most relevant to
277  * GUI programming (if something more substantial is required,
278  * something like boost or loki should be used).
279  *
280  * For conditional compilation, the library provides the
281  * Cgu::DoIf::mem_fun() utility functions which will conditionally
282  * compile a call to a non-static class member function if, and only
283  * if, the target object has that function as a member. If it does
284  * not have the member function as a member, the call will just do
285  * nothing rather than generate a compiler error, as it will also if
286  * the target object is const and the member function to be called is
287  * non-const. In addition Cgu::DoIf::fun() will conditionally compile
288  * a call to an ordinary function (or static member function) if, and
289  * only if, the target object is convertible to the type (say, a base
290  * type) held by pointer as the first argument of that function.
291  *
292  * They therefore provide compile-time inheritance checking based on
293  * the static type of the object passed to them. They save dynamic
294  * casting (and therefore run time overhead and the requirement for
295  * target types to have a virtual method) in templated functions when
296  * the static type is all that is necessary to enable type checking to
297  * be carried out.
298  *
299  * This is not just a template curiosity, but enables more generic
300  * programming practices when, say, passing mixins to templated
301  * functions. A templated function can be passed an object as a
302  * template type, and that function can then conditionally call member
303  * functions of objects passed to it. If the object has a particular
304  * function as a member, Cgu::DoIf::mem_fun() will call the function,
305  * and if not it will do nothing without causing a compilation error.
306  * It can be particularly useful for templated set-up or tear-down
307  * functions intended to take a wide variety of different objects with
308  * differing features.
309  *
310  * As mentioned above, Cgu::DoIf::mem_fun() and Cgu::DoIf::fun() will
311  * do nothing if an attempt is made to execute a non-const function on
312  * a const object, as well as if the object type does not match the
313  * function or member function sought to be invoked. If a compilation
314  * failure is wanted in a case of const mismatch instead of doing
315  * nothing, from version 2.0.1 the static assertion
316  * Cgu::DoIf::assert_not_const() can be invoked before the call to a
317  * non-const function is made by Cgu::DoIf::mem_fun() or
318  * Cgu::DoIf::fun().
319  *
320  * @b Non-static @b member @b functions
321  *
322  * The first argument to be passed to Cgu::DoIf::mem_fun() is the
323  * target object to be tested and the second argument is the
324  * non-static member function which is to be called with respect to
325  * that object if it has the function as a member. Any number of
326  * further arguments can be passed, representing the arguments to be
327  * provided to that member function. These further arguments may be
328  * reference arguments (const or non-const), value arguments or
329  * r-values, and for automatic pass-through they are passed by r-value
330  * reference and std::forward(), so no overhead should be created if
331  * value or r-value arguments are passed via Cgu::DoIf::mem_fun().
332  *
333  * As an example, take a class which uses multiple inheritance to
334  * inherit from Cgu::EmitterArg as a mixin (normally a class would
335  * have an Emitter object as a member, but it can be inherited from).
336  * A container of objects could have the emit() method called on them
337  * in a case where they do inherit from EmitterArg, where the code
338  * does nothing if they do not. For example:
339  * @code
340  * class Calc {
341  * public:
342  * void do_calc(void);
343  * };
344  *
345  * class CalcEmit: public Calc,
346  * public Cgu::EmitterArg<int> {
347  * };
348  *
349  * ... some code blocks elsewhere ...
350  *
351  * template <class T>
352  * void dispatch_calcs(const std::vector<T>& v) {
353  * int count;
354  * typename std::vector<T>::const_iterator iter;
355  * for (count = 0, iter = v.begin();
356  * iter != v.end();
357  * ++count, ++iter) {
358  * iter->do_calc();
359  * Cgu::DoIf::mem_fun(*iter, // object to be tested
360  * &Cgu::EmitterArg<int>::emit, // member function to be conditionally called
361  * count); // argument
362  * }
363  * }
364  * @endcode
365  *
366  * @b Ordinary @b functions @b and @b static @b member @b functions
367  *
368  * The use of Cgu::DoIf::fun() with normal functions and static member
369  * functions is similar to the use of mem_fun() with non-static member
370  * functions, except that the first argument of the function to be
371  * conditionally called must be a pointer to a type to which the
372  * target object can prospectively be converted. The first argument
373  * to be passed to Cgu::DoIf::fun() is the target object to be tested
374  * and the second argument is the function which is to be
375  * conditionally called if the conversion can be accomplished. If the
376  * function to be conditionally called is so called, the target object
377  * will be passed by pointer to it. Any number of further arguments
378  * can be passed to Cgu::DoIf::fun(), representing additional
379  * arguments to be provided to the function to be conditionally
380  * called, which may be reference arguments, value arguments or
381  * r-value reference arguments (and automatic pass-through is
382  * provided, as in the case of mem_fun()).
383  *
384  * The use of Cgu::DoIf::fun() with ordinary functions can be useful
385  * for batching a number of calls to be made to a test object. For
386  * example:
387  *
388  * @code
389  * class Calc {
390  * public:
391  * void do_calc();
392  * };
393  *
394  * class CalcEmit: public Calc,
395  * public Cgu::EmitterArg<int> {
396  * public:
397  * void clean_up(int);
398  * };
399  *
400  * ... some code blocks elsewhere ...
401  *
402  * void emit_on_calcs(CalcEmit* c, int count) {
403  * c->emit(count);
404  * c->clean_up(count);
405  * }
406  *
407  * template <class T>
408  * void dispatch_calcs(const std::vector<T>& v) {
409  * int count;
410  * typename std::vector<T>::const_iterator iter;
411  * for (count = 0, iter = v.begin();
412  * iter != v.end();
413  * ++count, ++iter) {
414  * iter->do_calc();
415  * Cgu::DoIf::fun(*iter, // object to be tested against first argument of function to be conditionally called
416  * &emit_on_calcs, // function to be conditionally called
417  * count); // second argument of function to be conditionally called
418  * }
419  * }
420  * @endcode
421  *
422  * @b Return @b values
423  *
424  * If the function to be called returns something other than void and
425  * the function to be conditionally called is not called, then
426  * mem_fun() and fun() pass back a dummy object of the return type
427  * using that type's default constructor. The returned object has no
428  * meaning beyond that in such a case, so it should not be relied on
429  * as holding anything other than its default value on default
430  * construction in a case of failure. This in turn means that any
431  * return value, if not a built-in type, must have a default
432  * constructor.
433  *
434  * @b Overloaded @b functions
435  *
436  * Where a referenced member function or ordinary function is
437  * overloaded, this will cause difficulties in template type deduction
438  * when mem_fun() or fun() is called, requiring explicit
439  * disambiguation. For example the following will fail to compile
440  * unless explicitly disambiguated:
441  * @code
442  * class A {
443  * public:
444  * void do_it(int i);
445  * void do_it(int i, int j);
446  * void do_it(double d);
447  * };
448  * int func(A* a, int i);
449  * int func(A* a, double d);
450  *
451  * template <class T>
452  * void do_it_if(T& t) {
453  * int i = 1, j = 2;
454  * double d = 10.0;
455  * Cgu::DoIf::mem_fun(t, &A::do_it, i); // won't compile
456  * Cgu::DoIf::mem_fun(t, &A::do_it, i, j); // won't compile
457  * Cgu::DoIf::mem_fun(t, &A::do_it, d); // won't compile
458  * Cgu::DoIf::fun(t, func, i); // won't compile
459  * Cgu::DoIf::fun(t, func, d); // won't compile
460  *
461  * Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int)>(&A::do_it), i); // OK
462  * Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int, int)>(&A::do_it), i, j); // OK
463  * Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(double)>(&A::do_it), d); // OK
464  * Cgu::DoIf::fun(t, static_cast<int (*)(A*, int)>(func), i); // OK
465  * Cgu::DoIf::fun(t, static_cast<int (*)(A*, double)>(func), d); // OK
466  * }
467  * @endcode
468  *
469  * @b Static @b assertion
470  *
471  * This library also provides the Cgu::DoIf::assert_related_to_type(),
472  * Cgu::DoIf::assert_related_types() and Cgu::DoIf::assert_same_type()
473  * static type-checking assertions. If the matters asserted are not
474  * true, a compile time error in the line where the functions are
475  * instantiated will occur.
476  *
477  * These static assertion functions can be viewed as doing the
478  * opposite of Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(). The
479  * mem_fun() and fun() functions will make a conditional call, and do
480  * nothing if the test condition is not met without a compile time or
481  * run time error, in order to provide compile time polymorphism. On
482  * the other hand, assert_related_to_type(), assert_related_types()
483  * and assert_same_type() cause an explicit compilation error where
484  * the test condition is not met at an ascertainable point in the code
485  * whilst avoiding a slew of incomprehensible error messages from the
486  * compiler. They enable compile time checking of type related
487  * invariants.
488  *
489  * In addition, from version 2.0.1, a Cgu::DoIf::assert_not_const()
490  * static assertion is available.
491  *
492  * The static assertions add nothing to the compiled object code.
493  * They either succeed or fail at compile time.
494  */
495 
496 #include <utility> // for std::forward
497 #include <type_traits> // for std::true_type, std::false_type and std::remove_const
498 
500 
501 namespace Cgu {
502 
503 namespace DoIf {
504 
505 /**
506  * @class RelatedTest do_if.h c++-gtk-utils/do_if.h
507  * @brief Class for compile time testing of inheritance relationships
508  * @sa DoIf::mem_fun DoIf::fun
509  *
510  * This class provides a compile time test of whether the Obj class
511  * template parameter type is related to the Base class template
512  * parameter type by public derivation, or they are of the same type:
513  * the 'value' public member will be true if they are, otherwise
514  * false. Everything in it comprises a compile time constant so that
515  * 'value' can be used as a template parameter for conditional
516  * complation, and can also be used with the std::enable_if template.
517  *
518  * This class tests convertibility, and constness is not discarded in
519  * making the test. Whilst a non-const type passed as the second
520  * template parameter will (if the other conditions referred to above
521  * are met) be shown as related to a const base type or const same
522  * type specified as the first template parameter type, the reverse is
523  * not true. This ensures that the DoIf::mem_fun() and DoIf::fun()
524  * conditional compilation functions work correctly.
525  */
526 
527 template<class Base, class Obj>
528 class RelatedTest {
529 
530  static std::true_type test(Base*);
531  static std::false_type test(...);
532 
533  typedef decltype(test(static_cast<Obj*>(0))) TestObjType;
534  typedef decltype(test(static_cast<void*>(0))) TestVoidType;
535 
536 public:
537 /**
538  * A compile time constant which indicates whether the Obj class
539  * template parameter type is related to the Base class template
540  * parameter type by public derivation, or they are of the same type.
541  * Because it is a compile time constant it can be used as a template
542  * parameter and therefore for conditional compilation.
543  *
544  * This constant specifies convertibility, and constness is not
545  * discarded in making the test. Whilst a non-const type passed as
546  * the second template parameter will (if the other conditions
547  * referred to above are met) be shown as related to a const base type
548  * or const same type specified as the first template parameter type,
549  * the reverse is not true. This ensures that the DoIf::mem_fun() and
550  * DoIf::fun() conditional compilation functions work correctly.
551  */
552  static const bool value = TestObjType::value == true
553  && TestVoidType::value == false;
554 };
555 
556 /**
557  * This function provides a compile time assertion that the static
558  * type of the second argument passed to it is related to (that is,
559  * either the same as or publicly derived from) the static type of the
560  * first argument. If it is not, a compile time error will occur
561  * (with a message that "Cgu::DoIf::assert_related_to_type() failed",
562  * and the line at which this function is reported as instantiated
563  * will be the line at which the assertion failed).
564  *
565  * For example "Cgu::DoIf::assert_related_to_type(a, b)" will fail to
566  * compile unless the static type of 'b' is the same as or publicly
567  * derived from the static type of 'a'. In making this test,
568  * constness is discarded and not taken into account.
569  *
570  * See assert_related_types() for a test where the ordering of the
571  * arguments is not significant.
572  *
573  * This function can be viewed as doing the opposite of
574  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
575  * error where the test is not met, rather than doing nothing.
576  * However, unlike those functions, as mentioned above
577  * assert_related_to_type() discards constness in making the test.
578  *
579  * It generates no object code, and is therefore thread safe and does
580  * not throw.
581  */
582 template <class Base, class Obj>
583 void assert_related_to_type(const Base& b, const Obj& o) {
584  static_assert(RelatedTest<Base, Obj>::value,
585  "Cgu::DoIf::assert_related_to_type() failed");
586 }
587 
588 /**
589  * This function provides a compile time assertion that the static
590  * type of the argument passed to it is related to (that is, either
591  * the same as or publicly derived from) the type given as the
592  * explicit template parameter to the function call. If it is not, a
593  * compile time error will occur (with a message that
594  * "Cgu::DoIf::assert_related_to_type() failed", and the line at which
595  * this function is reported as instantiated will be the line at which
596  * the assertion failed).
597  *
598  * For example "Cgu::DoIf::assert_related_to_type<A>(x)" will fail to
599  * compile unless the static type of 'x' is the same as or publicly
600  * derived from type A. In making this test, constness is discarded
601  * and not taken into account.
602  *
603  * This function can be viewed as doing the opposite of
604  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
605  * error where the test is not met, rather than doing nothing.
606  * However, unlike those functions, as mentioned above
607  * assert_related_to_type() discards constness in making the test.
608  *
609  * It generates no object code, and is therefore thread safe and does
610  * not throw.
611  */
612 template <class Base, class Obj>
613 void assert_related_to_type(const Obj& o) {
614  static_assert(RelatedTest<Base, Obj>::value,
615  "Cgu::DoIf::assert_related_to_type() failed");
616 }
617 
618 /**
619  * This function provides a compile time assertion that the static
620  * type of the first argument passed to it is the same as the static
621  * type of the second argument. If it is not, a compile time error
622  * will occur (with a message that "Cgu::DoIf::assert_same_type()
623  * failed", and the line at which this function is reported as
624  * instantiated will be the line at which the assertion failed).
625  *
626  * For example "Cgu::DoIf::assert_same_type(a, b)" will fail to
627  * compile unless the static types of 'a' and 'b' are the same. In
628  * making this test, constness is discarded and not taken into
629  * account: types can be the same even if one is const and the other
630  * is not.
631  *
632  * It generates no object code, and is therefore thread safe and does
633  * not throw.
634  */
635 template <class T1, class T2>
636 void assert_same_type(const T1& t1, const T2& t2) {
638  "Cgu::DoIf::assert_same_type() failed");
639 }
640 
641 /**
642  * This function provides a compile time assertion that the static
643  * type of the argument passed to it is the same as the type given as
644  * the explicit template parameter to the function call. If it is
645  * not, a compile time error will occur (with a message that
646  * "Cgu::DoIf::assert_same_type() failed", and the line at which this
647  * function is reported as instantiated will be the line at which the
648  * assertion failed).
649  *
650  * For example "Cgu::DoIf::assert_same_type<A>(x)" will fail to
651  * compile unless the static type of 'x' is type A. In making this
652  * test, constness is discarded and not taken into account: types can
653  * be the same even if one is const and the other is not.
654  *
655  * It generates no object code, and is therefore thread safe and does
656  * not throw.
657  *
658  * Earlier versions of this function had a bug. A const type could
659  * not be specified as the explicit template argument
660  * (Cgu::DoIf::assert_same_type<const A>(x) would not work). This was
661  * fixed in version 2.0.1.
662  */
663 template <class T1, class T2>
664 void assert_same_type(const T2& t2) {
665  // in the second conditional test, make T2 const in case the user
666  // specifies a const T1 parameter type
668  "Cgu::DoIf::assert_same_type() failed");
669 }
670 
671 /**
672  * This function provides a compile time assertion that the static
673  * type of the arguments passed are related to each other (that is,
674  * either they are the same or one is publicly derived from the
675  * other). If they are not, a compile time error will occur (with a
676  * message that "Cgu::DoIf::assert_related_types() failed", and the
677  * line at which this function is reported as instantiated will be the
678  * line at which the assertion failed).
679  *
680  * For example "Cgu::DoIf::assert_related_types(a, b)" will fail to
681  * compile unless the static types of 'a' and 'b' are the same or one
682  * of the static types is publicly derived from the other. In making
683  * this test, constness is discarded and not taken into account: types
684  * can be related even if one is const and the other is not.
685  *
686  * See assert_related_to_type() for a test where the ordering of the
687  * arguments is significant, so that which of them must be the base
688  * type can be stated.
689  *
690  * This function can be viewed as doing the opposite of
691  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
692  * error where the test is not met, rather than doing nothing.
693  * However, unlike those functions, as mentioned above
694  * assert_related_types() discards constness in making the test.
695  *
696  * It generates no object code, and is therefore thread safe and does
697  * not throw.
698  */
699 template <class T1, class T2>
700 void assert_related_types(const T1& t1, const T2& t2) {
702  "Cgu::DoIf::assert_related_types() failed");
703 }
704 
705 /**
706  * This function provides a compile time assertion that the static
707  * type of the argument passed is not const. If it is, a compile time
708  * error will occur (with a message that
709  * "Cgu::DoIf::assert_not_const() failed", and the line at which this
710  * function is reported as instantiated will be the line at which the
711  * assertion failed).
712  *
713  * For example 'Cgu::DoIf::assert_not_const(a)' will fail to compile
714  * unless the static type of 'a' is not const.
715  *
716  * It generates no object code, and is therefore thread safe and does
717  * not throw.
718  *
719  * Since 2.0.1
720  */
721 template <class T>
722 void assert_not_const(T& t) {
723  static_assert(RelatedTest<typename std::remove_const<T>::type, T>::value,
724  "Cgu::DoIf::assert_not_const() failed");
725 }
726 
727 #ifndef DOXYGEN_PARSING
728 
729 /*
730  These classes and associated helper function employ 'RelatedTest' to
731  implement conditional compilation using templates and derivation.
732  They can be used with non-static class functions, static class
733  functions.
734 */
735 /*
736  the static member functions for the 'false' specialisations take
737  Args... rather just an elipsis argument so that any argument can be
738  a non-POD type
739  */
740 
741 template <bool value, class Ret>
742 struct cond_call {};
743 
744 /* cond_call implementation */
745 
746 /* case of true with a return value */
747 
748 template <class Ret>
749 struct cond_call<true, Ret> {
750  template <class T, class Func, class... Args>
751  static Ret exec(T& obj,
752  Func func,
753  Args&&... args) {
754  return (obj.*func)(std::forward<Args>(args)...);
755  }
756 
757  template <class T, class Func, class... Args>
758  static Ret exec_static(T& obj,
759  Func func,
760  Args&&... args) {
761  return func(&obj, std::forward<Args>(args)...);
762  }
763 };
764 
765 /* case of false with a return value */
766 
767 template <class Ret>
768 struct cond_call<false, Ret> {
769  template <class T, class Func, class... Args>
770  static Ret exec(T&,
771  Func,
772  Args&&...) {
773  return Ret();
774  }
775 
776  template <class T, class Func, class... Args>
777  static Ret exec_static(T&,
778  Func,
779  Args&&...) {
780  return Ret();
781  }
782 };
783 
784 /* case of true with no return value */
785 
786 template <>
787 struct cond_call<true, void> {
788  template <class T, class Func, class... Args>
789  static void exec(T& obj,
790  Func func,
791  Args&&... args) {
792  (obj.*func)(std::forward<Args>(args)...);
793  }
794 
795  template <class T, class Func, class... Args>
796  static void exec_static(T& obj,
797  Func func,
798  Args&&... args) {
799  func(&obj, std::forward<Args>(args)...);
800  }
801 };
802 
803 /* case of false with no return value */
804 
805 template <>
806 struct cond_call<false, void> {
807  template <class T, class Func, class... Args>
808  static void exec(T&,
809  Func,
810  Args&&...) {}
811 
812  template <class T, class Func, class... Args>
813  static void exec_static(T&,
814  Func,
815  Args&&...) {}
816 };
817 
818 #endif /* DOXYGEN_PARSING */
819 
820 /* the mem_fun() forwarding functions */
821 
822 /* with return value */
823 
824 /**
825  * This function overload conditionally executes the member function
826  * passed as the second argument if the class object passed as the
827  * first argument has it as a member (say by derivation), otherwise it
828  * does nothing. This function is thread safe if the referenced
829  * member function is thread safe. It does not throw unless the
830  * referenced member function throws or (if its arguments are not
831  * built-in types nor reference arguments) the copy constructor of one
832  * of the member function's arguments throws, or (if no call is made)
833  * the return type's default constructor throws.
834  * @return The result of the function call, or if no call is made, an
835  * empty object obtained by calling the return type's default
836  * constructor.
837  */
838 template <class Base, class Obj, class Ret, class... Params, class... Args>
839 Ret mem_fun(Obj& obj,
840  Ret (Base::*func)(Params...),
841  Args&&... args) {
842  return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec(obj, func,
843  std::forward<Args>(args)...);
844 }
845 
846 /* no return value */
847 
848 /**
849  * This function overload conditionally executes the member function
850  * passed as the second argument if the class object passed as the
851  * first argument has it as a member (say by derivation), otherwise it
852  * does nothing. This function is thread safe if the referenced
853  * member function is thread safe. It does not throw unless the
854  * referenced member function throws or (if its arguments are not
855  * built-in types nor reference arguments) the copy constructor of one
856  * of the member function's arguments throws.
857  */
858 template <class Base, class Obj, class... Params, class... Args>
859 void mem_fun(Obj& obj,
860  void (Base::*func)(Params...),
861  Args&&... args) {
862  cond_call<RelatedTest<Base, Obj>::value, void>::exec(obj, func,
863  std::forward<Args>(args)...);
864 }
865 
866 /* for const member functions */
867 
868 /* with return value */
869 
870 /**
871  * This function overload conditionally executes the member function
872  * passed as the second argument if the class object passed as the
873  * first argument has it as a member (say by derivation), otherwise it
874  * does nothing. This function is thread safe if the referenced
875  * member function is thread safe. It does not throw unless the
876  * referenced member function throws or (if its arguments are not
877  * built-in types nor reference arguments) the copy constructor of one
878  * of the member function's arguments throws, or (if no call is made)
879  * the return type's default constructor throws.
880  * @return The result of the function call, or if no call is made, an
881  * empty object obtained by calling the return type's default
882  * constructor.
883  */
884 template <class Base, class Obj, class Ret, class... Params, class... Args>
885 Ret mem_fun(const Obj& obj,
886  Ret (Base::*func)(Params...) const,
887  Args&&... args) {
888  return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec(obj, func,
889  std::forward<Args>(args)...);
890 }
891 
892 /* no return value */
893 
894 /**
895  * This function overload conditionally executes the member function
896  * passed as the second argument if the class object passed as the
897  * first argument has it as a member (say by derivation), otherwise it
898  * does nothing. This function is thread safe if the referenced
899  * member function is thread safe. It does not throw unless the
900  * referenced member function throws or (if its arguments are not
901  * built-in types nor reference arguments) the copy constructor of one
902  * of the member function's arguments throws.
903  */
904 template <class Base, class Obj, class... Params, class... Args>
905 void mem_fun(const Obj& obj,
906  void (Base::*func)(Params...) const,
907  Args&&... args) {
908  cond_call<RelatedTest<Base, Obj>::value, void>::exec(obj, func,
909  std::forward<Args>(args)...);
910 }
911 
912 /* for ordinary functions and static member functions */
913 
914 /* with return value */
915 /**
916  * This function overload conditionally executes the function passed
917  * as the second argument if the object passed as the first argument
918  * relates to (ie is an instance of or derived from) the type to which
919  * the first argument of the function to be conditionally executed is
920  * a pointer, otherwise it does nothing. This function is thread safe
921  * if the referenced function to be called is thread safe. It does
922  * not throw unless the referenced function throws or (if its
923  * arguments are not built-in types nor reference arguments) the copy
924  * constructor of one of the referenced function's arguments throws,
925  * or (if no call is made) the return type's default constructor
926  * throws.
927  * @return The result of the function call, or if no call is made, an
928  * empty object obtained by calling the return type's default
929  * constructor.
930  */
931 template <class Base, class Obj, class Ret, class... Params, class... Args>
932 Ret fun(Obj& obj,
933  Ret (*func)(Base*, Params...),
934  Args&&... args) {
935  return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec_static(obj, func,
936  std::forward<Args>(args)...);
937 }
938 
939 /* no return value */
940 
941 /**
942  * This function overload conditionally executes the function passed
943  * as the second argument if the object passed as the first argument
944  * relates to (ie is an instance of or derived from) the type to which
945  * the first argument of the function to be conditionally executed is
946  * a pointer, otherwise it does nothing. This function is thread safe
947  * if the referenced function to be called is thread safe. It does
948  * not throw unless the referenced function throws or (if its
949  * arguments are not built-in types nor reference arguments) the copy
950  * constructor of one of the referenced function's arguments throws.
951  */
952 template <class Base, class Obj, class... Params, class... Args>
953 void fun(Obj& obj,
954  void (*func)(Base*, Params...),
955  Args&&... args) {
956  cond_call<RelatedTest<Base, Obj>::value, void>::exec_static(obj, func,
957  std::forward<Args>(args)...);
958 }
959 
960 } // namespace DoIf
961 
962 } // namespace Cgu
963 
964 #endif /* CGU_DO_IF */