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    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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, and can also be used with the std::enable_if template.
00517  *
00518  * This class tests convertibility, and constness is not discarded in
00519  * making the test.  Whilst a non-const type passed as the second
00520  * template parameter will (if the other conditions referred to above
00521  * are met) be shown as related to a const base type or const same
00522  * type specified as the first template parameter type, the reverse is
00523  * not true.  This ensures that the DoIf::mem_fun() and DoIf::fun()
00524  * conditional compilation functions work correctly.
00525  */
00526 
00527 template<class Base, class Obj>
00528 class RelatedTest {
00529 
00530   static std::true_type test(Base*);
00531   static std::false_type test(...);
00532 
00533   typedef decltype(test(static_cast<Obj*>(0))) TestObjType;
00534   typedef decltype(test(static_cast<void*>(0))) TestVoidType;
00535 
00536 public:
00537 /**
00538  * A compile time constant which indicates whether the Obj class
00539  * template parameter type is related to the Base class template
00540  * parameter type by public derivation, or they are of the same type.
00541  * Because it is a compile time constant it can be used as a template
00542  * parameter and therefore for conditional compilation.
00543  *
00544  * This constant specifies convertibility, and constness is not
00545  * discarded in making the test.  Whilst a non-const type passed as
00546  * the second template parameter will (if the other conditions
00547  * referred to above are met) be shown as related to a const base type
00548  * or const same type specified as the first template parameter type,
00549  * the reverse is not true.  This ensures that the DoIf::mem_fun() and
00550  * DoIf::fun() conditional compilation functions work correctly.
00551  */
00552   static const bool value = TestObjType::value == true
00553                             && TestVoidType::value == false;
00554 };
00555 
00556 /**
00557  * This function provides a compile time assertion that the static
00558  * type of the second argument passed to it is related to (that is,
00559  * either the same as or publicly derived from) the static type of the
00560  * first argument.  If it is not, a compile time error will occur
00561  * (with a message that "Cgu::DoIf::assert_related_to_type() failed",
00562  * and the line at which this function is reported as instantiated
00563  * will be the line at which the assertion failed).
00564  *
00565  * For example "Cgu::DoIf::assert_related_to_type(a, b)" will fail to
00566  * compile unless the static type of 'b' is the same as or publicly
00567  * derived from the static type of 'a'.  In making this test,
00568  * constness is discarded and not taken into account.
00569  *
00570  * See assert_related_types() for a test where the ordering of the
00571  * arguments is not significant.
00572  *
00573  * This function can be viewed as doing the opposite of
00574  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
00575  * error where the test is not met, rather than doing nothing.
00576  * However, unlike those functions, as mentioned above
00577  * assert_related_to_type() discards constness in making the test.
00578  *
00579  * It generates no object code, and is therefore thread safe and does
00580  * not throw.
00581  */
00582 template <class Base, class Obj>
00583 void assert_related_to_type(const Base& b, const Obj& o) {
00584   static_assert(RelatedTest<Base, Obj>::value,
00585                 "Cgu::DoIf::assert_related_to_type() failed");
00586 }
00587 
00588 /**
00589  * This function provides a compile time assertion that the static
00590  * type of the argument passed to it is related to (that is, either
00591  * the same as or publicly derived from) the type given as the
00592  * explicit template parameter to the function call.  If it is not, a
00593  * compile time error will occur (with a message that
00594  * "Cgu::DoIf::assert_related_to_type() failed", and the line at which
00595  * this function is reported as instantiated will be the line at which
00596  * the assertion failed).
00597  *
00598  * For example "Cgu::DoIf::assert_related_to_type<A>(x)" will fail to
00599  * compile unless the static type of 'x' is the same as or publicly
00600  * derived from type A.  In making this test, constness is discarded
00601  * and not taken into account.
00602  *
00603  * This function can be viewed as doing the opposite of
00604  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
00605  * error where the test is not met, rather than doing nothing.
00606  * However, unlike those functions, as mentioned above
00607  * assert_related_to_type() discards constness in making the test.
00608  *
00609  * It generates no object code, and is therefore thread safe and does
00610  * not throw.
00611  */
00612 template <class Base, class Obj>
00613 void assert_related_to_type(const Obj& o) {
00614   static_assert(RelatedTest<Base, Obj>::value,
00615                 "Cgu::DoIf::assert_related_to_type() failed");
00616 }
00617 
00618 /**
00619  * This function provides a compile time assertion that the static
00620  * type of the first argument passed to it is the same as the static
00621  * type of the second argument.  If it is not, a compile time error
00622  * will occur (with a message that "Cgu::DoIf::assert_same_type()
00623  * failed", and the line at which this function is reported as
00624  * instantiated will be the line at which the assertion failed).
00625  *
00626  * For example "Cgu::DoIf::assert_same_type(a, b)" will fail to
00627  * compile unless the static types of 'a' and 'b' are the same.  In
00628  * making this test, constness is discarded and not taken into
00629  * account: types can be the same even if one is const and the other
00630  * is not.
00631  *
00632  * It generates no object code, and is therefore thread safe and does
00633  * not throw.
00634  */
00635 template <class T1, class T2>
00636 void assert_same_type(const T1& t1, const T2& t2) {
00637   static_assert(RelatedTest<T1, T2>::value && RelatedTest<T2, T1>::value,
00638                 "Cgu::DoIf::assert_same_type() failed");
00639 }
00640 
00641 /**
00642  * This function provides a compile time assertion that the static
00643  * type of the argument passed to it is the same as the type given as
00644  * the explicit template parameter to the function call.  If it is
00645  * not, a compile time error will occur (with a message that
00646  * "Cgu::DoIf::assert_same_type() failed", and the line at which this
00647  * function is reported as instantiated will be the line at which the
00648  * assertion failed).
00649  *
00650  * For example "Cgu::DoIf::assert_same_type<A>(x)" will fail to
00651  * compile unless the static type of 'x' is type A.  In making this
00652  * test, constness is discarded and not taken into account: types can
00653  * be the same even if one is const and the other is not.
00654  *
00655  * It generates no object code, and is therefore thread safe and does
00656  * not throw.
00657  *
00658  * Earlier versions of this function had a bug.  A const type could
00659  * not be specified as the explicit template argument
00660  * (Cgu::DoIf::assert_same_type<const A>(x) would not work).  This was
00661  * fixed in version 2.0.1.
00662  */
00663 template <class T1, class T2>
00664 void assert_same_type(const T2& t2) {
00665   // in the second conditional test, make T2 const in case the user
00666   // specifies a const T1 parameter type
00667   static_assert(RelatedTest<T1, T2>::value && RelatedTest<const T2, T1>::value,
00668                 "Cgu::DoIf::assert_same_type() failed");
00669 }
00670 
00671 /**
00672  * This function provides a compile time assertion that the static
00673  * type of the arguments passed are related to each other (that is,
00674  * either they are the same or one is publicly derived from the
00675  * other).  If they are not, a compile time error will occur (with a
00676  * message that "Cgu::DoIf::assert_related_types() failed", and the
00677  * line at which this function is reported as instantiated will be the
00678  * line at which the assertion failed).
00679  *
00680  * For example "Cgu::DoIf::assert_related_types(a, b)" will fail to
00681  * compile unless the static types of 'a' and 'b' are the same or one
00682  * of the static types is publicly derived from the other.  In making
00683  * this test, constness is discarded and not taken into account: types
00684  * can be related even if one is const and the other is not.
00685  *
00686  * See assert_related_to_type() for a test where the ordering of the
00687  * arguments is significant, so that which of them must be the base
00688  * type can be stated.
00689  *
00690  * This function can be viewed as doing the opposite of
00691  * Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(): it causes a compilation
00692  * error where the test is not met, rather than doing nothing.
00693  * However, unlike those functions, as mentioned above
00694  * assert_related_types() discards constness in making the test.
00695  *
00696  * It generates no object code, and is therefore thread safe and does
00697  * not throw.
00698  */
00699 template <class T1, class T2>
00700 void assert_related_types(const T1& t1, const T2& t2) {
00701   static_assert(RelatedTest<T1, T2>::value || RelatedTest<T2, T1>::value,
00702                 "Cgu::DoIf::assert_related_types() failed");
00703 }
00704 
00705 /**
00706  * This function provides a compile time assertion that the static
00707  * type of the argument passed is not const.  If it is, a compile time
00708  * error will occur (with a message that
00709  * "Cgu::DoIf::assert_not_const() failed", and the line at which this
00710  * function is reported as instantiated will be the line at which the
00711  * assertion failed).
00712  *
00713  * For example 'Cgu::DoIf::assert_not_const(a)' will fail to compile
00714  * unless the static type of 'a' is not const.
00715  *
00716  * It generates no object code, and is therefore thread safe and does
00717  * not throw.
00718  *
00719  * Since 2.0.1
00720  */
00721 template <class T>
00722 void assert_not_const(T& t) {
00723   static_assert(RelatedTest<typename std::remove_const<T>::type, T>::value,
00724                 "Cgu::DoIf::assert_not_const() failed");
00725 }
00726 
00727 #ifndef DOXYGEN_PARSING
00728 
00729 /*
00730   These classes and associated helper function employ 'RelatedTest' to
00731   implement conditional compilation using templates and derivation.
00732   They can be used with non-static class functions, static class
00733   functions.
00734 */
00735 /*
00736   the static member functions for the 'false' specialisations take
00737   Args... rather just an elipsis argument so that any argument can be
00738   a non-POD type
00739  */
00740 
00741 template <bool value, class Ret>
00742 struct cond_call {};
00743 
00744 /* cond_call implementation */
00745 
00746 /* case of true with a return value */
00747 
00748 template <class Ret>
00749 struct cond_call<true, Ret> {
00750   template <class T, class Func, class... Args>
00751   static Ret exec(T& obj,
00752                   Func func,
00753                   Args&&... args) {
00754     return (obj.*func)(std::forward<Args>(args)...);
00755   }
00756 
00757   template <class T, class Func, class... Args>
00758   static Ret exec_static(T& obj,
00759                          Func func,
00760                          Args&&... args) {
00761     return func(&obj, std::forward<Args>(args)...);
00762   }
00763 };
00764 
00765 /* case of false with a return value */
00766 
00767 template <class Ret>
00768 struct cond_call<false, Ret> {
00769   template <class T, class Func, class... Args>
00770   static Ret exec(T&,
00771                   Func,
00772                   Args&&...) {
00773     return Ret();
00774   }
00775 
00776   template <class T, class Func, class... Args>
00777   static Ret exec_static(T&,
00778                          Func,
00779                          Args&&...) {
00780     return Ret();
00781   }
00782 };
00783 
00784 /* case of true with no return value */
00785 
00786 template <>
00787 struct cond_call<true, void> {
00788   template <class T, class Func, class... Args>
00789   static void exec(T& obj,
00790                    Func func,
00791                    Args&&... args) {
00792     (obj.*func)(std::forward<Args>(args)...);
00793   }
00794 
00795   template <class T, class Func, class... Args>
00796   static void exec_static(T& obj,
00797                           Func func,
00798                           Args&&... args) {
00799     func(&obj, std::forward<Args>(args)...);
00800   }
00801 };
00802 
00803 /* case of false with no return value */
00804 
00805 template <>
00806 struct cond_call<false, void> {
00807   template <class T, class Func, class... Args>
00808   static void exec(T&,
00809                    Func,
00810                    Args&&...) {}
00811 
00812   template <class T, class Func, class... Args>
00813   static void exec_static(T&,
00814                           Func,
00815                           Args&&...) {}
00816 };
00817 
00818 #endif /* DOXYGEN_PARSING */
00819 
00820 /* the mem_fun() forwarding functions */
00821 
00822 /* with return value */
00823 
00824 /**
00825  * This function overload conditionally executes the member function
00826  * passed as the second argument if the class object passed as the
00827  * first argument has it as a member (say by derivation), otherwise it
00828  * does nothing.  This function is thread safe if the referenced
00829  * member function is thread safe.  It does not throw unless the
00830  * referenced member function throws or (if its arguments are not
00831  * built-in types nor reference arguments) the copy constructor of one
00832  * of the member function's arguments throws, or (if no call is made)
00833  * the return type's default constructor throws.
00834  * @return The result of the function call, or if no call is made, an
00835  * empty object obtained by calling the return type's default
00836  * constructor.
00837  */
00838 template <class Base, class Obj, class Ret, class... Params, class... Args>
00839 Ret mem_fun(Obj& obj,
00840             Ret (Base::*func)(Params...),
00841             Args&&... args) {
00842   return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec(obj, func,
00843                                                              std::forward<Args>(args)...);
00844 }
00845 
00846 /* no return value */
00847 
00848 /**
00849  * This function overload conditionally executes the member function
00850  * passed as the second argument if the class object passed as the
00851  * first argument has it as a member (say by derivation), otherwise it
00852  * does nothing.  This function is thread safe if the referenced
00853  * member function is thread safe.  It does not throw unless the
00854  * referenced member function throws or (if its arguments are not
00855  * built-in types nor reference arguments) the copy constructor of one
00856  * of the member function's arguments throws.
00857  */
00858 template <class Base, class Obj, class... Params, class... Args>
00859 void mem_fun(Obj& obj,
00860              void (Base::*func)(Params...),
00861              Args&&... args) {
00862   cond_call<RelatedTest<Base, Obj>::value, void>::exec(obj, func,
00863                                                        std::forward<Args>(args)...);
00864 }
00865 
00866 /* for const member functions */
00867 
00868 /* with return value */
00869 
00870 /**
00871  * This function overload conditionally executes the member function
00872  * passed as the second argument if the class object passed as the
00873  * first argument has it as a member (say by derivation), otherwise it
00874  * does nothing.  This function is thread safe if the referenced
00875  * member function is thread safe.  It does not throw unless the
00876  * referenced member function throws or (if its arguments are not
00877  * built-in types nor reference arguments) the copy constructor of one
00878  * of the member function's arguments throws, or (if no call is made)
00879  * the return type's default constructor throws.
00880  * @return The result of the function call, or if no call is made, an
00881  * empty object obtained by calling the return type's default
00882  * constructor.
00883  */
00884 template <class Base, class Obj, class Ret, class... Params, class... Args>
00885 Ret mem_fun(const Obj& obj,
00886             Ret (Base::*func)(Params...) const,
00887             Args&&... args) {
00888   return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec(obj, func,
00889                                                              std::forward<Args>(args)...);
00890 }
00891 
00892 /* no return value */
00893 
00894 /**
00895  * This function overload conditionally executes the member function
00896  * passed as the second argument if the class object passed as the
00897  * first argument has it as a member (say by derivation), otherwise it
00898  * does nothing.  This function is thread safe if the referenced
00899  * member function is thread safe.  It does not throw unless the
00900  * referenced member function throws or (if its arguments are not
00901  * built-in types nor reference arguments) the copy constructor of one
00902  * of the member function's arguments throws.
00903  */
00904 template <class Base, class Obj, class... Params, class... Args>
00905 void mem_fun(const Obj& obj,
00906              void (Base::*func)(Params...) const,
00907              Args&&... args) {
00908   cond_call<RelatedTest<Base, Obj>::value, void>::exec(obj, func,
00909                                                        std::forward<Args>(args)...);
00910 }
00911 
00912 /* for ordinary functions and static member functions */
00913 
00914 /* with return value */
00915 /**
00916  * This function overload conditionally executes the function passed
00917  * as the second argument if the object passed as the first argument
00918  * relates to (ie is an instance of or derived from) the type to which
00919  * the first argument of the function to be conditionally executed is
00920  * a pointer, otherwise it does nothing.  This function is thread safe
00921  * if the referenced function to be called is thread safe.  It does
00922  * not throw unless the referenced function throws or (if its
00923  * arguments are not built-in types nor reference arguments) the copy
00924  * constructor of one of the referenced function's arguments throws,
00925  * or (if no call is made) the return type's default constructor
00926  * throws.
00927  * @return The result of the function call, or if no call is made, an
00928  * empty object obtained by calling the return type's default
00929  * constructor.
00930  */
00931 template <class Base, class Obj, class Ret, class... Params, class... Args>
00932 Ret fun(Obj& obj,
00933         Ret (*func)(Base*, Params...),
00934         Args&&... args) {
00935   return cond_call<RelatedTest<Base, Obj>::value, Ret>::exec_static(obj, func,
00936                                                                     std::forward<Args>(args)...);
00937 }
00938 
00939 /* no return value */
00940 
00941 /**
00942  * This function overload conditionally executes the function passed
00943  * as the second argument if the object passed as the first argument
00944  * relates to (ie is an instance of or derived from) the type to which
00945  * the first argument of the function to be conditionally executed is
00946  * a pointer, otherwise it does nothing.  This function is thread safe
00947  * if the referenced function to be called is thread safe.  It does
00948  * not throw unless the referenced function throws or (if its
00949  * arguments are not built-in types nor reference arguments) the copy
00950  * constructor of one of the referenced function's arguments throws.
00951  */
00952 template <class Base, class Obj, class... Params, class... Args>
00953 void fun(Obj& obj,
00954          void (*func)(Base*, Params...),
00955          Args&&... args) {
00956   cond_call<RelatedTest<Base, Obj>::value, void>::exec_static(obj, func,
00957                                                               std::forward<Args>(args)...);
00958 }
00959 
00960 } // namespace DoIf
00961 
00962 } // namespace Cgu
00963 
00964 #endif /* CGU_DO_IF */