c++-gtk-utils
do_if.h
Go to the documentation of this file.
00001 /* Copyright (C) 2010 and 2011 Chris Vine
00002 
00003 The library comprised in this file or of which this file is part is
00004 distributed by Chris Vine under the GNU Lesser General Public
00005 License as follows:
00006 
00007    This library is free software; you can redistribute it and/or
00008    modify it under the terms of the GNU Lesser General Public License
00009    as published by the Free Software Foundation; either version 2.1 of
00010    the License, or (at your option) any later version.
00011 
00012    This library is distributed in the hope that it will be useful, but
00013    WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015    Lesser General Public License, version 2.1, for more details.
00016 
00017    You should have received a copy of the GNU Lesser General Public
00018    License, version 2.1, along with this library (see the file LGPL.TXT
00019    which came with this source code package in the c++-gtk-utils
00020    sub-directory); if not, write to the Free Software Foundation, Inc.,
00021    59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA.
00022 
00023 However, it is not intended that the object code of a program whose
00024 source code instantiates a template from this file or uses macros or
00025 inline functions (of any length) should by reason only of that
00026 instantiation or use be subject to the restrictions of use in the GNU
00027 Lesser General Public License.  With that in mind, the words "and
00028 macros, inline functions and instantiations of templates (of any
00029 length)" shall be treated as substituted for the words "and small
00030 macros and small inline functions (ten lines or less in length)" in
00031 the fourth paragraph of section 5 of that licence.  This does not
00032 affect any other reason why object code may be subject to the
00033 restrictions in that licence (nor for the avoidance of doubt does it
00034 affect the application of section 2 of that licence to modifications
00035 of the source code in this file).
00036 
00037 */
00038 
00039 #ifndef CGU_DO_IF_H
00040 #define CGU_DO_IF_H
00041 
00042 /**
00043  * @file do_if.h
00044  * @brief This file provides utility functions for conditional compilation.
00045  *
00046  * \#include <c++-gtk-utils/do_if.h>
00047  *
00048  * The DoIf namespace of the library provides a small subset of
00049  * template meta-programming techniques likely to be most relevant to
00050  * GUI programming (if something more substantial is required,
00051  * something like boost or loki should be used).
00052  *
00053  * For conditional compilation, the library provides the
00054  * Cgu::DoIf::mem_fun() utility functions which will conditionally
00055  * compile a call to a non-static class member function if, and only
00056  * if, the target object has that function as a member.  If it does
00057  * not have the member function as a member, the call will just do
00058  * nothing rather than generate a compiler error, as it will also if
00059  * the target object is const and the member function to be called is
00060  * non-const.  In addition Cgu::DoIf::fun() will conditionally compile
00061  * a call to an ordinary function (or static member function) if, and
00062  * only if, the target object is convertible to the type (say, a base
00063  * type) held by pointer as the first argument of that function.
00064  *
00065  * They therefore provide compile-time inheritance checking based on
00066  * the static type of the object passed to them.  They save dynamic
00067  * casting (and therefore run time overhead and the requirement for
00068  * target types to have a virtual method) in templated functions when
00069  * the static type is all that is necessary to enable type checking to
00070  * be carried out.
00071  *
00072  * This is not just a template curiosity, but enables more generic
00073  * programming practices when, say, passing mixins to templated
00074  * functions.  A templated function can be passed an object as a
00075  * template type, and that function can then conditionally call member
00076  * functions of objects passed to it.  If the object has a particular
00077  * function as a member, Cgu::DoIf::mem_fun() will call the function,
00078  * and if not it will do nothing without causing a compilation error.
00079  * It can be particularly useful for templated set-up or tear-down
00080  * functions intended to take a wide variety of different objects with
00081  * differing features.
00082  *
00083  * As mentioned above, Cgu::DoIf::mem_fun() and Cgu::DoIf::fun() will
00084  * do nothing if an attempt is made to execute a non-const function on
00085  * a const object, as well as if the object type does not match the
00086  * function or member function sought to be invoked.  If a compilation
00087  * failure is wanted in a case of const mismatch instead of doing
00088  * nothing, from version 2.0.1 the static assertion
00089  * Cgu::DoIf::assert_not_const() can be invoked before the call to a
00090  * non-const function is made by Cgu::DoIf::mem_fun() or
00091  * Cgu::DoIf::fun().
00092  *
00093  * @b Non-static @b member @b functions
00094  *
00095  * The first argument to be passed to Cgu::DoIf::mem_fun() is the
00096  * target object to be tested and the second argument is the
00097  * non-static member function which is to be called with respect to
00098  * that object if it has the function as a member.  Any number of
00099  * further arguments can be passed, representing the arguments to be
00100  * provided to that member function.  These further arguments may be
00101  * reference arguments (const or non-const), value arguments or
00102  * r-values, and for automatic pass-through they are passed by r-value
00103  * reference and std::forward(), so no overhead should be created if
00104  * value or r-value arguments are passed via Cgu::DoIf::mem_fun().
00105  *
00106  * As an example, take a class which uses multiple inheritance to
00107  * inherit from Cgu::EmitterArg as a mixin (normally a class would
00108  * have an Emitter object as a member, but it can be inherited from).
00109  * A container of objects could have the emit() method called on them
00110  * in a case where they do inherit from EmitterArg, where the code
00111  * does nothing if they do not.  For example:
00112  * @code
00113  *   class Calc {
00114  *   public:
00115  *     void do_calc(void);
00116  *   };
00117  *
00118  *   class CalcEmit: public Calc,
00119  *                   public Cgu::EmitterArg<int> {
00120  *   };
00121  *
00122  *   ... some code blocks elsewhere ...
00123  *
00124  *   template <class T>
00125  *   void dispatch_calcs(const std::vector<T>& v) {
00126  *     int count;
00127  *     typename std::vector<T>::const_iterator iter;
00128  *     for (count = 0, iter = v.begin();
00129  *          iter != v.end();
00130  *          ++count, ++iter) {
00131  *       iter->do_calc();
00132  *       Cgu::DoIf::mem_fun(*iter,                       // object to be tested
00133  *                          &Cgu::EmitterArg<int>::emit, // member function to be conditionally called
00134  *                          count);                      // argument
00135  *     }
00136  *   }
00137  * @endcode
00138  *
00139  * @b Ordinary @b functions @b and @b static @b member @b functions
00140  *
00141  * The use of Cgu::DoIf::fun() with normal functions and static member
00142  * functions is similar to the use of mem_fun() with non-static member
00143  * functions, except that the first argument of the function to be
00144  * conditionally called must be a pointer to a type to which the
00145  * target object can prospectively be converted.  The first argument
00146  * to be passed to Cgu::DoIf::fun() is the target object to be tested
00147  * and the second argument is the function which is to be
00148  * conditionally called if the conversion can be accomplished.  If the
00149  * function to be conditionally called is so called, the target object
00150  * will be passed by pointer to it.  Any number of further arguments
00151  * can be passed to Cgu::DoIf::fun(), representing additional
00152  * arguments to be provided to the function to be conditionally
00153  * called, which may be reference arguments, value arguments or
00154  * r-value reference arguments (and automatic pass-through is
00155  * provided, as in the case of mem_fun()).
00156  *
00157  * The use of Cgu::DoIf::fun() with ordinary functions can be useful
00158  * for batching a number of calls to be made to a test object.  For
00159  * example:
00160  *
00161  * @code
00162  *   class Calc {
00163  *   public:
00164  *     void do_calc();
00165  *   };
00166  *
00167  *   class CalcEmit: public Calc,
00168  *                   public Cgu::EmitterArg<int> {
00169  *   public:
00170  *     void clean_up(int);
00171  *   };
00172  *
00173  *   ... some code blocks elsewhere ...
00174  *
00175  *   void emit_on_calcs(CalcEmit* c, int count) {
00176  *     c->emit(count);
00177  *     c->clean_up(count);
00178  *   }
00179  *
00180  *   template <class T>
00181  *   void dispatch_calcs(const std::vector<T>& v) {
00182  *     int count;
00183  *     typename std::vector<T>::const_iterator iter;
00184  *     for (count = 0, iter = v.begin();
00185  *          iter != v.end();
00186  *          ++count, ++iter) {
00187  *       iter->do_calc();
00188  *       Cgu::DoIf::fun(*iter,          // object to be tested against first argument of function to be conditionally called
00189  *                      &emit_on_calcs, // function to be conditionally called
00190  *                      count);         // second argument of function to be conditionally called
00191  *     }
00192  *   }
00193  * @endcode
00194  *
00195  * @b Return @b values
00196  *
00197  * If the function to be called returns something other than void and
00198  * the function to be conditionally called is not called, then
00199  * mem_fun() and fun() pass back a dummy object of the return type
00200  * using that type's default constructor.  The returned object has no
00201  * meaning beyond that in such a case, so it should not be relied on
00202  * as holding anything other than its default value on default
00203  * construction in a case of failure.  This in turn means that any
00204  * return value, if not a built-in type, must have a default
00205  * constructor.
00206  *
00207  * @b Overloaded @b functions
00208  *
00209  * Where a referenced member function or ordinary function is
00210  * overloaded, this will cause difficulties in template type deduction
00211  * when mem_fun() or fun() is called, requiring explicit
00212  * disambiguation.  For example the following will fail to compile
00213  * unless explicitly disambiguated:
00214  * @code
00215  *   class A {
00216  *   public:
00217  *     void do_it(int i);
00218  *     void do_it(int i, int j);
00219  *     void do_it(double d);
00220  *   };
00221  *   int func(A* a, int i);
00222  *   int func(A* a, double d);
00223  *
00224  *   template <class T>
00225  *   void do_it_if(T& t) {
00226  *     int i = 1, j = 2;
00227  *     double d = 10.0;
00228  *     Cgu::DoIf::mem_fun(t, &A::do_it, i);                                        // won't compile
00229  *     Cgu::DoIf::mem_fun(t, &A::do_it, i, j);                                     // won't compile
00230  *     Cgu::DoIf::mem_fun(t, &A::do_it, d);                                        // won't compile
00231  *     Cgu::DoIf::fun(t, func, i);                                                 // won't compile
00232  *     Cgu::DoIf::fun(t, func, d);                                                 // won't compile
00233  *
00234  *     Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int)>(&A::do_it), i);         // OK
00235  *     Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int, int)>(&A::do_it), i, j); // OK
00236  *     Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(double)>(&A::do_it), d);      // OK
00237  *     Cgu::DoIf::fun(t, static_cast<int (*)(A*, int)>(func), i);                  // OK
00238  *     Cgu::DoIf::fun(t, static_cast<int (*)(A*, double)>(func), d);               // OK
00239  *   }
00240  * @endcode
00241  *
00242  * @b Static @b assertion
00243  *
00244  * This library also provides the Cgu::DoIf::assert_related_to_type(),
00245  * Cgu::DoIf::assert_related_types() and Cgu::DoIf::assert_same_type()
00246  * static type-checking assertions.  If the matters asserted are not
00247  * true, a compile time error in the line where the functions are
00248  * instantiated will occur.
00249  *
00250  * These static assertion functions can be viewed as doing the
00251  * opposite of Cgu::DoIf::mem_fun() and Cgu::DoIf::fun().  The
00252  * mem_fun() and fun() functions will make a conditional call, and do
00253  * nothing if the test condition is not met without a compile time or
00254  * run time error, in order to provide compile time polymorphism.  On
00255  * the other hand, assert_related_to_type(), assert_related_types()
00256  * and assert_same_type() cause an explicit compilation error where
00257  * the test condition is not met at an ascertainable point in the code
00258  * whilst avoiding a slew of incomprehensible error messages from the
00259  * compiler.  They enable compile time checking of type related
00260  * invariants.
00261  *
00262  * In addition, from version 2.0.1, a Cgu::DoIf::assert_not_const()
00263  * static assertion is available.
00264  *
00265  * The static assertions add nothing to the compiled object code.
00266  * They either succeed or fail at compile time.
00267  */
00268 
00269 /**
00270  * @namespace Cgu::DoIf
00271  * @brief This namespace provides utility functions for conditional compilation.
00272  *
00273  * \#include <c++-gtk-utils/do_if.h>
00274  *
00275  * The DoIf namespace of the library provides a small subset of
00276  * template meta-programming techniques likely to be most relevant to
00277  * GUI programming (if something more substantial is required,
00278  * something like boost or loki should be used).
00279  *
00280  * For conditional compilation, the library provides the
00281  * Cgu::DoIf::mem_fun() utility functions which will conditionally
00282  * compile a call to a non-static class member function if, and only
00283  * if, the target object has that function as a member.  If it does
00284  * not have the member function as a member, the call will just do
00285  * nothing rather than generate a compiler error, as it will also if
00286  * the target object is const and the member function to be called is
00287  * non-const.  In addition Cgu::DoIf::fun() will conditionally compile
00288  * a call to an ordinary function (or static member function) if, and
00289  * only if, the target object is convertible to the type (say, a base
00290  * type) held by pointer as the first argument of that function.
00291  *
00292  * They therefore provide compile-time inheritance checking based on
00293  * the static type of the object passed to them.  They save dynamic
00294  * casting (and therefore run time overhead and the requirement for
00295  * target types to have a virtual method) in templated functions when
00296  * the static type is all that is necessary to enable type checking to
00297  * be carried out.
00298  *
00299  * This is not just a template curiosity, but enables more generic
00300  * programming practices when, say, passing mixins to templated
00301  * functions.  A templated function can be passed an object as a
00302  * template type, and that function can then conditionally call member
00303  * functions of objects passed to it.  If the object has a particular
00304  * function as a member, Cgu::DoIf::mem_fun() will call the function,
00305  * and if not it will do nothing without causing a compilation error.
00306  * It can be particularly useful for templated set-up or tear-down
00307  * functions intended to take a wide variety of different objects with
00308  * differing features.
00309  *
00310  * As mentioned above, Cgu::DoIf::mem_fun() and Cgu::DoIf::fun() will
00311  * do nothing if an attempt is made to execute a non-const function on
00312  * a const object, as well as if the object type does not match the
00313  * function or member function sought to be invoked.  If a compilation
00314  * failure is wanted in a case of const mismatch instead of doing
00315  * nothing, from version 2.0.1 the static assertion
00316  * Cgu::DoIf::assert_not_const() can be invoked before the call to a
00317  * non-const function is made by Cgu::DoIf::mem_fun() or
00318  * Cgu::DoIf::fun().
00319  *
00320  * @b Non-static @b member @b functions
00321  *
00322  * The first argument to be passed to Cgu::DoIf::mem_fun() is the
00323  * target object to be tested and the second argument is the
00324  * non-static member function which is to be called with respect to
00325  * that object if it has the function as a member.  Any number of
00326  * further arguments can be passed, representing the arguments to be
00327  * provided to that member function.  These further arguments may be
00328  * reference arguments (const or non-const), value arguments or
00329  * r-values, and for automatic pass-through they are passed by r-value
00330  * reference and std::forward(), so no overhead should be created if
00331  * value or r-value arguments are passed via Cgu::DoIf::mem_fun().
00332  *
00333  * As an example, take a class which uses multiple inheritance to
00334  * inherit from Cgu::EmitterArg as a mixin (normally a class would
00335  * have an Emitter object as a member, but it can be inherited from).
00336  * A container of objects could have the emit() method called on them
00337  * in a case where they do inherit from EmitterArg, where the code
00338  * does nothing if they do not.  For example:
00339  * @code
00340  *   class Calc {
00341  *   public:
00342  *     void do_calc(void);
00343  *   };
00344  *
00345  *   class CalcEmit: public Calc,
00346  *                   public Cgu::EmitterArg<int> {
00347  *   };
00348  *
00349  *   ... some code blocks elsewhere ...
00350  *
00351  *   template <class T>
00352  *   void dispatch_calcs(const std::vector<T>& v) {
00353  *     int count;
00354  *     typename std::vector<T>::const_iterator iter;
00355  *     for (count = 0, iter = v.begin();
00356  *          iter != v.end();
00357  *          ++count, ++iter) {
00358  *       iter->do_calc();
00359  *       Cgu::DoIf::mem_fun(*iter,                       // object to be tested
00360  *                          &Cgu::EmitterArg<int>::emit, // member function to be conditionally called
00361  *                          count);                      // argument
00362  *     }
00363  *   }
00364  * @endcode
00365  *
00366  * @b Ordinary @b functions @b and @b static @b member @b functions
00367  *
00368  * The use of Cgu::DoIf::fun() with normal functions and static member
00369  * functions is similar to the use of mem_fun() with non-static member
00370  * functions, except that the first argument of the function to be
00371  * conditionally called must be a pointer to a type to which the
00372  * target object can prospectively be converted.  The first argument
00373  * to be passed to Cgu::DoIf::fun() is the target object to be tested
00374  * and the second argument is the function which is to be
00375  * conditionally called if the conversion can be accomplished.  If the
00376  * function to be conditionally called is so called, the target object
00377  * will be passed by pointer to it.  Any number of further arguments
00378  * can be passed to Cgu::DoIf::fun(), representing additional
00379  * arguments to be provided to the function to be conditionally
00380  * called, which may be reference arguments, value arguments or
00381  * r-value reference arguments (and automatic pass-through is
00382  * provided, as in the case of mem_fun()).
00383  *
00384  * The use of Cgu::DoIf::fun() with ordinary functions can be useful
00385  * for batching a number of calls to be made to a test object.  For
00386  * example:
00387  *
00388  * @code
00389  *   class Calc {
00390  *   public:
00391  *     void do_calc();
00392  *   };
00393  *
00394  *   class CalcEmit: public Calc,
00395  *                   public Cgu::EmitterArg<int> {
00396  *   public:
00397  *     void clean_up(int);
00398  *   };
00399  *
00400  *   ... some code blocks elsewhere ...
00401  *
00402  *   void emit_on_calcs(CalcEmit* c, int count) {
00403  *     c->emit(count);
00404  *     c->clean_up(count);
00405  *   }
00406  *
00407  *   template <class T>
00408  *   void dispatch_calcs(const std::vector<T>& v) {
00409  *     int count;
00410  *     typename std::vector<T>::const_iterator iter;
00411  *     for (count = 0, iter = v.begin();
00412  *          iter != v.end();
00413  *          ++count, ++iter) {
00414  *       iter->do_calc();
00415  *       Cgu::DoIf::fun(*iter,          // object to be tested against first argument of function to be conditionally called
00416  *                      &emit_on_calcs, // function to be conditionally called
00417  *                      count);         // second argument of function to be conditionally called
00418  *     }
00419  *   }
00420  * @endcode
00421  *
00422  * @b Return @b values
00423  *
00424  * If the function to be called returns something other than void and
00425  * the function to be conditionally called is not called, then
00426  * mem_fun() and fun() pass back a dummy object of the return type
00427  * using that type's default constructor.  The returned object has no
00428  * meaning beyond that in such a case, so it should not be relied on
00429  * as holding anything other than its default value on default
00430  * construction in a case of failure.  This in turn means that any
00431  * return value, if not a built-in type, must have a default
00432  * constructor.
00433  *
00434  * @b Overloaded @b functions
00435  *
00436  * Where a referenced member function or ordinary function is
00437  * overloaded, this will cause difficulties in template type deduction
00438  * when mem_fun() or fun() is called, requiring explicit
00439  * disambiguation.  For example the following will fail to compile
00440  * unless explicitly disambiguated:
00441  * @code
00442  *   class A {
00443  *   public:
00444  *     void do_it(int i);
00445  *     void do_it(int i, int j);
00446  *     void do_it(double d);
00447  *   };
00448  *   int func(A* a, int i);
00449  *   int func(A* a, double d);
00450  *
00451  *   template <class T>
00452  *   void do_it_if(T& t) {
00453  *     int i = 1, j = 2;
00454  *     double d = 10.0;
00455  *     Cgu::DoIf::mem_fun(t, &A::do_it, i);                                        // won't compile
00456  *     Cgu::DoIf::mem_fun(t, &A::do_it, i, j);                                     // won't compile
00457  *     Cgu::DoIf::mem_fun(t, &A::do_it, d);                                        // won't compile
00458  *     Cgu::DoIf::fun(t, func, i);                                                 // won't compile
00459  *     Cgu::DoIf::fun(t, func, d);                                                 // won't compile
00460  *
00461  *     Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int)>(&A::do_it), i);         // OK
00462  *     Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(int, int)>(&A::do_it), i, j); // OK
00463  *     Cgu::DoIf::mem_fun(t, static_cast<void (A::*)(double)>(&A::do_it), d);      // OK
00464  *     Cgu::DoIf::fun(t, static_cast<int (*)(A*, int)>(func), i);                  // OK
00465  *     Cgu::DoIf::fun(t, static_cast<int (*)(A*, double)>(func), d);               // OK
00466  *   }
00467  * @endcode
00468  *
00469  * @b Static @b assertion
00470  *
00471  * This library also provides the Cgu::DoIf::assert_related_to_type(),
00472  * Cgu::DoIf::assert_related_types() and Cgu::DoIf::assert_same_type()
00473  * static type-checking assertions.  If the matters asserted are not
00474  * true, a compile time error in the line where the functions are
00475  * instantiated will occur.
00476  *
00477  * These static assertion functions can be viewed as doing the
00478  * opposite of Cgu::DoIf::mem_fun() and Cgu::DoIf::fun().  The
00479  * mem_fun() and fun() functions will make a conditional call, and do
00480  * nothing if the test condition is not met without a compile time or
00481  * run time error, in order to provide compile time polymorphism.  On
00482  * the other hand, assert_related_to_type(), assert_related_types()
00483  * and assert_same_type() cause an explicit compilation error where
00484  * the test condition is not met at an ascertainable point in the code
00485  * whilst avoiding a slew of incomprehensible error messages from the
00486  * compiler.  They enable compile time checking of type related
00487  * invariants.
00488  *
00489  * In addition, from version 2.0.1, a Cgu::DoIf::assert_not_const()
00490  * static assertion is available.
00491  *
00492  * The static assertions add nothing to the compiled object code.
00493  * They either succeed or fail at compile time.
00494  */
00495 
00496 #include <utility>     // for std::forward
00497 #include <type_traits> // for std::true_type, std::false_type and std::remove_const
00498 
00499 #include <c++-gtk-utils/cgu_config.h>
00500 
00501 namespace Cgu {
00502 
00503 namespace DoIf {
00504 
00505 /**
00506  * @class RelatedTest do_if.h c++-gtk-utils/do_if.h
00507  * @brief Class for compile time testing of inheritance relationships
00508  * @sa mem_fun fun
00509  *
00510  * This class provides a compile time test of whether the Obj class
00511  * template parameter type is related to the Base class template
00512  * parameter type by public derivation, or they are of the same type:
00513  * the 'value' public member will be true if they are, otherwise
00514  * false.  Everything in it comprises a compile time constant so that
00515  * 'value' can be used as a template parameter for conditional
00516  * complation.  Because 'RelatedTest' has a static member named
00517  * 'value', it can also be used with boost's 'enable_if' templates.
00518  *
00519  * This class tests convertibility, and constness is not discarded in
00520  * making the test.  Whilst a non-const type passed as the second
00521  * template parameter will (if the other conditions referred to above
00522  * are met) be shown as related to a const base type or const same
00523  * type specified as the first template parameter type, the reverse is
00524  * not true.  This ensures that the DoIf::mem_fun() and DoIf::fun()
00525  * conditional compilation functions work correctly.
00526  */
00527 
00528 template<class Base, class Obj>
00529 class RelatedTest {
00530 
00531   static std::true_type test(Base*);
00532   static std::false_type test(...);
00533 
00534   typedef decltype(test(static_cast<Obj*>(0))) TestObjType;
00535   typedef decltype(test(static_cast<void*>(0))) TestVoidType;
00536 
00537 public:
00538 /**
00539  * A compile time constant which indicates whether the Obj class
00540  * template parameter type is related to the Base class template
00541  * parameter type by public derivation, or they are of the same type.
00542  * Because it is a compile time constant it can be used as a template
00543  * parameter and therefore for conditional compilation.
00544  *
00545  * This constant specifies convertibility, and constness is not
00546  * discarded in making the test.  Whilst a non-const type passed as
00547  * the second template parameter will (if the other conditions
00548  * referred to above are met) be shown as related to a const base type
00549  * or const same type specified as the first template parameter type,
00550  * the reverse is not true.  This ensures that the DoIf::mem_fun() and
00551  * DoIf::fun() conditional compilation functions work correctly.
00552  */
00553   static const bool value = TestObjType::value == true
00554                             && TestVoidType::value == false;
00555 };
00556 
00557 /**
00558  * This function provides a compile time assertion that the static
00559  * type of the second argument passed to it is related to (that is,
00560  * either the same as or publicly derived from) the static type of the
00561  * first argument.  If it is not, a compile time error will occur
00562  * (with a message that "Cgu::DoIf::assert_related_to_type() failed",
00563  * and the line at which this function is reported as instantiated
00564  * will be the line at which the assertion failed).
00565  *
00566  * For example "Cgu::DoIf::assert_related_to_type(a, b)" will fail to
00567  * compile unless the static type of 'b' is the same as or publicly
00568  * derived from the static type of 'a'.  In making this test,
00569  * constness is discarded and not taken into account.
00570  *
00571  * See assert_related_types() for a test where the ordering of the
00572  * arguments is not significant.
00573  *
00574  * This function can be viewed as doing the opposite of
00575  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
00576  * error where the test is not met, rather than doing nothing.
00577  * However, unlike those functions, as mentioned above
00578  * assert_related_to_type() discards constness in making the test.
00579  *
00580  * It generates no object code, and is therefore thread safe and does
00581  * not throw.
00582  */
00583 template <class Base, class Obj>
00584 void assert_related_to_type(const Base& b, const Obj& o) {
00585   static_assert(RelatedTest<Base, Obj>::value,
00586                 "Cgu::DoIf::assert_related_to_type() failed");
00587 }
00588 
00589 /**
00590  * This function provides a compile time assertion that the static
00591  * type of the argument passed to it is related to (that is, either
00592  * the same as or publicly derived from) the type given as the
00593  * explicit template parameter to the function call.  If it is not, a
00594  * compile time error will occur (with a message that
00595  * "Cgu::DoIf::assert_related_to_type() failed", and the line at which
00596  * this function is reported as instantiated will be the line at which
00597  * the assertion failed).
00598  *
00599  * For example "Cgu::DoIf::assert_related_to_type<A>(x)" will fail to
00600  * compile unless the static type of 'x' is the same as or publicly
00601  * derived from type A.  In making this test, constness is discarded
00602  * and not taken into account.
00603  *
00604  * This function can be viewed as doing the opposite of
00605  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
00606  * error where the test is not met, rather than doing nothing.
00607  * However, unlike those functions, as mentioned above
00608  * assert_related_to_type() discards constness in making the test.
00609  *
00610  * It generates no object code, and is therefore thread safe and does
00611  * not throw.
00612  */
00613 template <class Base, class Obj>
00614 void assert_related_to_type(const Obj& o) {
00615   static_assert(RelatedTest<Base, Obj>::value,
00616                 "Cgu::DoIf::assert_related_to_type() failed");
00617 }
00618 
00619 /**
00620  * This function provides a compile time assertion that the static
00621  * type of the first argument passed to it is the same as the static
00622  * type of the second argument.  If it is not, a compile time error
00623  * will occur (with a message that "Cgu::DoIf::assert_same_type()
00624  * failed", and the line at which this function is reported as
00625  * instantiated will be the line at which the assertion failed).
00626  *
00627  * For example "Cgu::DoIf::assert_same_type(a, b)" will fail to
00628  * compile unless the static types of 'a' and 'b' are the same.  In
00629  * making this test, constness is discarded and not taken into
00630  * account: types can be the same even if one is const and the other
00631  * is not.
00632  *
00633  * It generates no object code, and is therefore thread safe and does
00634  * not throw.
00635  */
00636 template <class T1, class T2>
00637 void assert_same_type(const T1& t1, const T2& t2) {
00638   static_assert(RelatedTest<T1, T2>::value && RelatedTest<T2, T1>::value,
00639                 "Cgu::DoIf::assert_same_type() failed");
00640 }
00641 
00642 /**
00643  * This function provides a compile time assertion that the static
00644  * type of the argument passed to it is the same as the type given as
00645  * the explicit template parameter to the function call.  If it is
00646  * not, a compile time error will occur (with a message that
00647  * "Cgu::DoIf::assert_same_type() failed", and the line at which this
00648  * function is reported as instantiated will be the line at which the
00649  * assertion failed).
00650  *
00651  * For example "Cgu::DoIf::assert_same_type<A>(x)" will fail to
00652  * compile unless the static type of 'x' is type A.  In making this
00653  * test, constness is discarded and not taken into account: types can
00654  * be the same even if one is const and the other is not.
00655  *
00656  * It generates no object code, and is therefore thread safe and does
00657  * not throw.
00658  *
00659  * Earlier versions of this function had a bug.  A const type could
00660  * not be specified as the explicit template argument
00661  * (Cgu::DoIf::assert_same_type<const A>(x) would not work).  This was
00662  * fixed in version 2.0.1.
00663  */
00664 template <class T1, class T2>
00665 void assert_same_type(const T2& t2) {
00666   // in the second conditional test, make T2 const in case the user
00667   // specifies a const T1 parameter type
00668   static_assert(RelatedTest<T1, T2>::value && RelatedTest<const T2, T1>::value,
00669                 "Cgu::DoIf::assert_same_type() failed");
00670 }
00671 
00672 /**
00673  * This function provides a compile time assertion that the static
00674  * type of the arguments passed are related to each other (that is,
00675  * either they are the same or one is publicly derived from the
00676  * other).  If they are not, a compile time error will occur (with a
00677  * message that "Cgu::DoIf::assert_related_types() failed", and the
00678  * line at which this function is reported as instantiated will be the
00679  * line at which the assertion failed).
00680  *
00681  * For example "Cgu::DoIf::assert_related_types(a, b)" will fail to
00682  * compile unless the static types of 'a' and 'b' are the same or one
00683  * of the static types is publicly derived from the other.  In making
00684  * this test, constness is discarded and not taken into account: types
00685  * can be related even if one is const and the other is not.
00686  *
00687  * See assert_related_to_type() for a test where the ordering of the
00688  * arguments is significant, so that which of them must be the base
00689  * type can be stated.
00690  *
00691  * This function can be viewed as doing the opposite of
00692  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
00693  * error where the test is not met, rather than doing nothing.
00694  * However, unlike those functions, as mentioned above
00695  * assert_related_types() discards constness in making the test.
00696  *
00697  * It generates no object code, and is therefore thread safe and does
00698  * not throw.
00699  */
00700 template <class T1, class T2>
00701 void assert_related_types(const T1& t1, const T2& t2) {
00702   static_assert(RelatedTest<T1, T2>::value || RelatedTest<T2, T1>::value,
00703                 "Cgu::DoIf::assert_related_types() failed");
00704 }
00705 
00706 /**
00707  * This function provides a compile time assertion that the static
00708  * type of the argument passed is not const.  If it is, a compile time
00709  * error will occur (with a message that
00710  * "Cgu::DoIf::assert_not_const() failed", and the line at which this
00711  * function is reported as instantiated will be the line at which the
00712  * assertion failed).
00713  *
00714  * For example 'Cgu::DoIf::assert_not_const(a)' will fail to compile
00715  * unless the static type of 'a' is not const.
00716  *
00717  * It generates no object code, and is therefore thread safe and does
00718  * not throw.
00719  *
00720  * Since 2.0.1
00721  */
00722 template <class T>
00723 void assert_not_const(T& t) {
00724   static_assert(RelatedTest<typename std::remove_const<T>::type, T>::value,
00725                 "Cgu::DoIf::assert_not_const() failed");
00726 }
00727 
00728 #ifndef DOXYGEN_PARSING
00729 
00730 /*
00731   These classes and associated helper function employ 'RelatedTest' to
00732   implement conditional compilation using templates and derivation.
00733   They can be used with non-static class functions, static class
00734   functions.
00735 */
00736 /*
00737   the static member functions for the 'false' specialisations take
00738   Args... rather just an elipsis argument so that any argument can be
00739   a non-POD type
00740  */
00741 
00742 template <bool value, class Ret>
00743 struct cond_call {};
00744 
00745 /* cond_call implementation */
00746 
00747 /* case of true with a return value */
00748 
00749 template <class Ret>
00750 struct cond_call<true, Ret> {
00751   template <class T, class Func, class... Args>
00752   static Ret exec(T& obj,
00753                   Func func,
00754                   Args&&... args) {
00755     return (obj.*func)(std::forward<Args>(args)...);
00756   }
00757 
00758   template <class T, class Func, class... Args>
00759   static Ret exec_static(T& obj,
00760                          Func func,
00761                          Args&&... args) {
00762     return func(&obj, std::forward<Args>(args)...);
00763   }
00764 };
00765 
00766 /* case of false with a return value */
00767 
00768 template <class Ret>
00769 struct cond_call<false, Ret> {
00770   template <class T, class Func, class... Args>
00771   static Ret exec(T&,
00772                   Func,
00773                   Args&&...) {
00774     return Ret();
00775   }
00776 
00777   template <class T, class Func, class... Args>
00778   static Ret exec_static(T&,
00779                          Func,
00780                          Args&&...) {
00781     return Ret();
00782   }
00783 };
00784 
00785 /* case of true with no return value */
00786 
00787 template <>
00788 struct cond_call<true, void> {
00789   template <class T, class Func, class... Args>
00790   static void exec(T& obj,
00791                    Func func,
00792                    Args&&... args) {
00793     (obj.*func)(std::forward<Args>(args)...);
00794   }
00795 
00796   template <class T, class Func, class... Args>
00797   static void exec_static(T& obj,
00798                           Func func,
00799                           Args&&... args) {
00800     func(&obj, std::forward<Args>(args)...);
00801   }
00802 };
00803 
00804 /* case of false with no return value */
00805 
00806 template <>
00807 struct cond_call<false, void> {
00808   template <class T, class Func, class... Args>
00809   static void exec(T&,
00810                    Func,
00811                    Args&&...) {}
00812 
00813   template <class T, class Func, class... Args>
00814   static void exec_static(T&,
00815                           Func,
00816                           Args&&...) {}
00817 };
00818 
00819 #endif /* DOXYGEN_PARSING */
00820 
00821 /* the mem_fun() forwarding functions */
00822 
00823 /* with return value */
00824 
00825 /**
00826  * This function overload conditionally executes the member function
00827  * passed as the second argument if the class object passed as the
00828  * first argument has it as a member (say by derivation), otherwise it
00829  * does nothing.  This function is thread safe if the referenced
00830  * member function is thread safe.  It does not throw unless the
00831  * referenced member function throws or (if its arguments are not
00832  * built-in types nor reference arguments) the copy constructor of one
00833  * of the member function's arguments throws, or (if no call is made)
00834  * the return type's default constructor throws.
00835  * @return The result of the function call, or if no call is made, an
00836  * empty object obtained by calling the return type's default
00837  * constructor.
00838  */
00839 template <class Base, class Obj, class Ret, class... Params, class... Args>
00840 Ret mem_fun(Obj& obj,
00841             Ret (Base::*func)(Params...),
00842             Args&&... args) {
00843   return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec(obj, func,
00844                                                              std::forward<Args>(args)...);
00845 }
00846 
00847 /* no return value */
00848 
00849 /**
00850  * This function overload conditionally executes the member function
00851  * passed as the second argument if the class object passed as the
00852  * first argument has it as a member (say by derivation), otherwise it
00853  * does nothing.  This function is thread safe if the referenced
00854  * member function is thread safe.  It does not throw unless the
00855  * referenced member function throws or (if its arguments are not
00856  * built-in types nor reference arguments) the copy constructor of one
00857  * of the member function's arguments throws.
00858  */
00859 template <class Base, class Obj, class... Params, class... Args>
00860 void mem_fun(Obj& obj,
00861              void (Base::*func)(Params...),
00862              Args&&... args) {
00863   cond_call<RelatedTest<Base, Obj>::value, void>::exec(obj, func,
00864                                                        std::forward<Args>(args)...);
00865 }
00866 
00867 /* for const member functions */
00868 
00869 /* with return value */
00870 
00871 /**
00872  * This function overload conditionally executes the member function
00873  * passed as the second argument if the class object passed as the
00874  * first argument has it as a member (say by derivation), otherwise it
00875  * does nothing.  This function is thread safe if the referenced
00876  * member function is thread safe.  It does not throw unless the
00877  * referenced member function throws or (if its arguments are not
00878  * built-in types nor reference arguments) the copy constructor of one
00879  * of the member function's arguments throws, or (if no call is made)
00880  * the return type's default constructor throws.
00881  * @return The result of the function call, or if no call is made, an
00882  * empty object obtained by calling the return type's default
00883  * constructor.
00884  */
00885 template <class Base, class Obj, class Ret, class... Params, class... Args>
00886 Ret mem_fun(const Obj& obj,
00887             Ret (Base::*func)(Params...) const,
00888             Args&&... args) {
00889   return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec(obj, func,
00890                                                              std::forward<Args>(args)...);
00891 }
00892 
00893 /* no return value */
00894 
00895 /**
00896  * This function overload conditionally executes the member function
00897  * passed as the second argument if the class object passed as the
00898  * first argument has it as a member (say by derivation), otherwise it
00899  * does nothing.  This function is thread safe if the referenced
00900  * member function is thread safe.  It does not throw unless the
00901  * referenced member function throws or (if its arguments are not
00902  * built-in types nor reference arguments) the copy constructor of one
00903  * of the member function's arguments throws.
00904  */
00905 template <class Base, class Obj, class... Params, class... Args>
00906 void mem_fun(const Obj& obj,
00907              void (Base::*func)(Params...) const,
00908              Args&&... args) {
00909   cond_call<RelatedTest<Base, Obj>::value, void>::exec(obj, func,
00910                                                        std::forward<Args>(args)...);
00911 }
00912 
00913 /* for ordinary functions and static member functions */
00914 
00915 /* with return value */
00916 /**
00917  * This function overload conditionally executes the function passed
00918  * as the second argument if the object passed as the first argument
00919  * relates to (ie is an instance of or derived from) the type to which
00920  * the first argument of the function to be conditionally executed is
00921  * a pointer, otherwise it does nothing.  This function is thread safe
00922  * if the referenced function to be called is thread safe.  It does
00923  * not throw unless the referenced function throws or (if its
00924  * arguments are not built-in types nor reference arguments) the copy
00925  * constructor of one of the referenced function's arguments throws,
00926  * or (if no call is made) the return type's default constructor
00927  * throws.
00928  * @return The result of the function call, or if no call is made, an
00929  * empty object obtained by calling the return type's default
00930  * constructor.
00931  */
00932 template <class Base, class Obj, class Ret, class... Params, class... Args>
00933 Ret fun(Obj& obj,
00934         Ret (*func)(Base*, Params...),
00935         Args&&... args) {
00936   return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec_static(obj, func,
00937                                                                     std::forward<Args>(args)...);
00938 }
00939 
00940 /* no return value */
00941 
00942 /**
00943  * This function overload conditionally executes the function passed
00944  * as the second argument if the object passed as the first argument
00945  * relates to (ie is an instance of or derived from) the type to which
00946  * the first argument of the function to be conditionally executed is
00947  * a pointer, otherwise it does nothing.  This function is thread safe
00948  * if the referenced function to be called is thread safe.  It does
00949  * not throw unless the referenced function throws or (if its
00950  * arguments are not built-in types nor reference arguments) the copy
00951  * constructor of one of the referenced function's arguments throws.
00952  */
00953 template <class Base, class Obj, class... Params, class... Args>
00954 void fun(Obj& obj,
00955          void (*func)(Base*, Params...),
00956          Args&&... args) {
00957   cond_call<RelatedTest<Base, Obj>::value, void>::exec_static(obj, func,
00958                                                               std::forward<Args>(args)...);
00959 }
00960 
00961 } // namespace DoIf
00962 
00963 } // namespace Cgu
00964 
00965 #endif /* CGU_DO_IF */