c++-gtk-utils
|
This file provides utility functions for conditional compilation. More...
Go to the source code of this file.
Classes | |
class | Cgu::DoIf::RelatedTest< Base, Obj > |
Class for compile time testing of inheritance relationships. More... | |
class | Cgu::DoIf::StaticAssertion |
Class for compile time assertion that a statement is true. More... | |
struct | Cgu::DoIf::StaticAssertion< true > |
class | Cgu::DoIf::RemoveConst< T > |
Class for removing a const qualifier. More... | |
struct | Cgu::DoIf::RemoveConst< const T > |
class | Cgu::DoIf::SucceedOnTrue< value > |
Struct which provides a type 'T' (typedef'ed to void*) if its template parameter is true. More... | |
struct | Cgu::DoIf::SucceedOnTrue< true > |
class | Cgu::DoIf::SucceedOnFalse< value > |
Struct which provides a type 'T' (typedef'ed to void*) if its template parameter is false. More... | |
struct | Cgu::DoIf::SucceedOnFalse< false > |
Namespaces | |
Cgu::DoIf | |
This namespace provides utility functions for conditional compilation. | |
Cgu | |
Functions | |
template<class Base , class Obj > | |
void | Cgu::DoIf::assert_related_to_type (const Base &b, const Obj &o) |
template<class Base , class Obj > | |
void | Cgu::DoIf::assert_related_to_type (const Obj &o) |
template<class T1 , class T2 > | |
void | Cgu::DoIf::assert_same_type (const T1 &t1, const T2 &t2) |
template<class T1 , class T2 > | |
void | Cgu::DoIf::assert_same_type (const T2 &t2) |
template<class T1 , class T2 > | |
void | Cgu::DoIf::assert_related_types (const T1 &t1, const T2 &t2) |
template<class T > | |
void | Cgu::DoIf::assert_not_const (T &t) |
template<class Base , class Obj , class Ret , class Arg1 , class Arg2 > | |
Ret | Cgu::DoIf::mem_fun (Obj &obj, Ret(Base::*func)(Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType arg1, typename Cgu::Param< Arg2 >::ParamType arg2, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg1 , class Arg2 > | |
Ret | Cgu::DoIf::mem_fun (Obj &, Ret(Base::*)(Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType, typename Cgu::Param< Arg2 >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg > | |
Ret | Cgu::DoIf::mem_fun (Obj &obj, Ret(Base::*func)(Arg), typename Cgu::Param< Arg >::ParamType arg, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg > | |
Ret | Cgu::DoIf::mem_fun (Obj &, Ret(Base::*)(Arg), typename Cgu::Param< Arg >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret > | |
Ret | Cgu::DoIf::mem_fun (Obj &obj, Ret(Base::*func)(), typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret > | |
Ret | Cgu::DoIf::mem_fun (Obj &, Ret(Base::*)(), typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg1 , class Arg2 > | |
void | Cgu::DoIf::mem_fun (Obj &obj, void(Base::*func)(Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType arg1, typename Cgu::Param< Arg2 >::ParamType arg2, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg1 , class Arg2 > | |
void | Cgu::DoIf::mem_fun (Obj &, void(Base::*)(Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType, typename Cgu::Param< Arg2 >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg > | |
void | Cgu::DoIf::mem_fun (Obj &obj, void(Base::*func)(Arg), typename Cgu::Param< Arg >::ParamType arg, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg > | |
void | Cgu::DoIf::mem_fun (Obj &, void(Base::*)(Arg), typename Cgu::Param< Arg >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj > | |
void | Cgu::DoIf::mem_fun (Obj &obj, void(Base::*func)(), typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj > | |
void | Cgu::DoIf::mem_fun (Obj &, void(Base::*)(), typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg1 , class Arg2 > | |
Ret | Cgu::DoIf::mem_fun (const Obj &obj, Ret(Base::*func)(Arg1, Arg2) const, typename Cgu::Param< Arg1 >::ParamType arg1, typename Cgu::Param< Arg2 >::ParamType arg2, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg1 , class Arg2 > | |
Ret | Cgu::DoIf::mem_fun (const Obj &, Ret(Base::*)(Arg1, Arg2) const, typename Cgu::Param< Arg1 >::ParamType, typename Cgu::Param< Arg2 >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg > | |
Ret | Cgu::DoIf::mem_fun (const Obj &obj, Ret(Base::*func)(Arg) const, typename Cgu::Param< Arg >::ParamType arg, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg > | |
Ret | Cgu::DoIf::mem_fun (const Obj &, Ret(Base::*)(Arg) const, typename Cgu::Param< Arg >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret > | |
Ret | Cgu::DoIf::mem_fun (const Obj &obj, Ret(Base::*func)() const, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret > | |
Ret | Cgu::DoIf::mem_fun (const Obj &, Ret(Base::*)() const, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg1 , class Arg2 > | |
void | Cgu::DoIf::mem_fun (const Obj &obj, void(Base::*func)(Arg1, Arg2) const, typename Cgu::Param< Arg1 >::ParamType arg1, typename Cgu::Param< Arg2 >::ParamType arg2, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg1 , class Arg2 > | |
void | Cgu::DoIf::mem_fun (const Obj &, void(Base::*)(Arg1, Arg2) const, typename Cgu::Param< Arg1 >::ParamType, typename Cgu::Param< Arg2 >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg > | |
void | Cgu::DoIf::mem_fun (const Obj &obj, void(Base::*func)(Arg) const, typename Cgu::Param< Arg >::ParamType arg, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg > | |
void | Cgu::DoIf::mem_fun (const Obj &, void(Base::*)(Arg) const, typename Cgu::Param< Arg >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj > | |
void | Cgu::DoIf::mem_fun (const Obj &obj, void(Base::*func)() const, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj > | |
void | Cgu::DoIf::mem_fun (const Obj &, void(Base::*)() const, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg1 , class Arg2 > | |
Ret | Cgu::DoIf::fun (Obj &obj, Ret(*func)(Base *, Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType arg1, typename Cgu::Param< Arg2 >::ParamType arg2, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg1 , class Arg2 > | |
Ret | Cgu::DoIf::fun (Obj &, Ret(*)(Base *, Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType, typename Cgu::Param< Arg2 >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg > | |
Ret | Cgu::DoIf::fun (Obj &obj, Ret(*func)(Base *, Arg), typename Cgu::Param< Arg >::ParamType arg, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret , class Arg > | |
Ret | Cgu::DoIf::fun (Obj &, Ret(*)(Base *, Arg), typename Cgu::Param< Arg >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret > | |
Ret | Cgu::DoIf::fun (Obj &obj, Ret(*func)(Base *), typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Ret > | |
Ret | Cgu::DoIf::fun (Obj &, Ret(*)(Base *), typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg1 , class Arg2 > | |
void | Cgu::DoIf::fun (Obj &obj, void(*func)(Base *, Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType arg1, typename Cgu::Param< Arg2 >::ParamType arg2, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg1 , class Arg2 > | |
void | Cgu::DoIf::fun (Obj &, void(*)(Base *, Arg1, Arg2), typename Cgu::Param< Arg1 >::ParamType, typename Cgu::Param< Arg2 >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg > | |
void | Cgu::DoIf::fun (Obj &obj, void(*func)(Base *, Arg), typename Cgu::Param< Arg >::ParamType arg, typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj , class Arg > | |
void | Cgu::DoIf::fun (Obj &, void(*)(Base *, Arg), typename Cgu::Param< Arg >::ParamType, typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj > | |
void | Cgu::DoIf::fun (Obj &obj, void(*func)(Base *), typename SucceedOnTrue< RelatedTest< Base, Obj >::value >::T t=0) |
template<class Base , class Obj > | |
void | Cgu::DoIf::fun (Obj &, void(*)(Base *), typename SucceedOnFalse< RelatedTest< Base, Obj >::value >::T t=0) |
This file provides utility functions for conditional compilation.
#include <c++-gtk-utils/do_if.h>
From version 1.2.10, the library provides a small subset of template meta-programming techniques likely to be most relevant to GUI programming (if something more substantial is required, something like boost or loki should be used).
For conditional compilation, the library provides the Cgu::DoIf::mem_fun() utility functions which will conditionally compile a call to a non-static class member function if, and only if, the target object has that function as a member. If it does not have the member function as a member, the call will just do nothing rather than generate a compiler error, as it will also if the target object is const and the member function to be called is non-const. In addition Cgu::DoIf::fun() will conditionally compile a call to an ordinary function (or static member function) if, and only if, the target object is convertible to the type (say, a base type) held by pointer as the first argument of that function.
They therefore provide compile-time inheritance checking based on the static type of the object passed to them. They save dynamic casting (and therefore run time overhead and the requirement for target types to have a virtual method) in templated functions when the static type is all that is necessary to enable type checking to be carried out.
This is not just a template curiosity, but enables more generic programming practices when, say, passing mixins to templated functions. A templated function can be passed an object as a template type, and that function can then conditionally call member functions of objects passed to it. If the object has a particular function as a member, Cgu::DoIf::mem_fun() will call the function, and if not it will do nothing without causing a compilation error. It can be particularly useful for templated set-up or tear-down functions intended to take a wide variety of different objects with differing features.
As mentioned above, Cgu::DoIf::mem_fun() and Cgu::DoIf::fun() will do nothing if an attempt is made to execute a non-const function on a const object, as well as if the object type does not match the function or member function sought to be invoked. If a compilation failure is wanted in a case of const mismatch instead of doing nothing, from version 1.2.15 the static assertion Cgu::DoIf::assert_not_const() can be invoked before the call to a non-const function is made by Cgu::DoIf::mem_fun() or Cgu::DoIf::fun().
The first argument to be passed to Cgu::DoIf::mem_fun() is the target object to be tested, the second argument is the non-static member function which is to be called with respect to that object if it has the function as a member, and up to two further arguments can be passed representing the arguments to be provided to that member function. These arguments may be reference arguments (const or non-const), and they are passed by a Param struct which uses template partial specialisation in order to provide automatic type mapping for arguments, so if they are value arguments they will be passed by reference to const: therefore, no copying of value arguments should arise by virtue of routing the calls through Cgu::DoIf::mem_fun().
As an example, take a class which uses multiple inheritance to inherit from Cgu::EmitterArg as a mixin (normally a class would have an Emitter object as a member, but it can be inherited from). A container of objects could have the emit() method called on them in a case where they do inherit from EmitterArg, where the code does nothing if they do not. For example:
The use of Cgu::DoIf::fun() with normal functions and static member functions is similar to the use of mem_fun() with non-static member functions, except that the first argument of the function to be conditionally called must be a pointer to a type to which the target object can prospectively be converted. The first argument to be passed to Cgu::DoIf::fun() is the target object to be tested and the second argument is the function which is to be conditionally called if the conversion can be accomplished. If the function to be conditionally called is so called, the target object will be passed by pointer to it. Up to two further arguments can be passed to Cgu::DoIf::fun() representing up to two additional arguments to be provided to the function to be conditionally called, which may be reference arguments or value arguments (and if value arguments they will be passed by reference to const, as in the case of mem_fun()).
The use of Cgu::DoIf::fun() with ordinary functions can be useful for batching a number of calls to be made to a test object. For example:
If the function to be called returns something other than void and the function to be conditionally called is not called, then mem_fun() and fun() pass back a dummy object of the return type using that type's default constructor. The returned object has no meaning beyond that in such a case, so it should not be relied on as holding anything other than its default value on default construction in a case of failure. This in turn means that any return value, if not a built-in type, must have a default constructor.
Where a referenced member function or ordinary function is overloaded, this may cause difficulties in template type deduction when mem_fun() or fun() is called. Functions may be overloaded on numbers of argument without difficulty. For example:
However, they cannot be overloaded on types without explicit disambiguation when mem_fun() or fun() is called. For example the following will fail to compile unless explicitly disambiguated:
This library also provides the Cgu::DoIf::assert_related_to_type(), Cgu::DoIf::assert_related_types() and Cgu::DoIf::assert_same_type() static type-checking assertions. If the matters asserted are not true, a compile time error in the line where the the functions are instantiated will occur (with a message that an incomplete type 'struct DoIf::StaticAssertion<false>' has been used).
These static assertion functions can be viewed as doing the opposite of Cgu::DoIf::mem_fun() and Cgu::DoIf::fun(). The mem_fun() and fun() functions will make a conditional call, and do nothing if the test condition is not met without a compile time or run time error, in order to provide compile time polymorphism. On the other hand, assert_related_to_type(), assert_related_types() and assert_same_type() cause an explicit compilation error where the test condition is not met at an ascertainable point in the code whilst avoiding a slew of incomprehensible error messages from the compiler. They enable compile time checking of type related invariants.
In addition, from version 1.2.15, a Cgu::DoIf::assert_not_const() static assertion is available.
The static assertions add nothing to the compiled object code. They either succeed or fail at compile time.