Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/kicklib/src/libraries/core/command/Functor.h @ 8071

Last change on this file since 8071 was 8071, checked in by rgrieder, 14 years ago

Merged ois_update branch (before it was renamed to mac_osx) into kicklib branch.

  • Property svn:eol-style set to native
File size: 50.5 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @file
31    @ingroup Command FunctorExecutor
32    @brief Definition of orxonox::Functor and its specialized subclasses, as well as the createFunctor() functions.
33
34    @anchor FunctorExample
35
36    Functors can be used to wrap function-pointers. While function-pointers have a very
37    complicated syntax in C++, Functors are always the same and you can call the wrapped
38    function-pointer independently of its parameter with arguments of type MultiType. These
39    arguments are then automatically converted to the right type.
40
41    To create a Functor, the helper function createFunctor() is used. It returns an instance
42    of orxonox::FunctorPtr which is simply a typedef of @ref orxonox::SharedPtr "SharedPtr<Functor>".
43    This means you don't have to delete the Functor after using it, because it is managed
44    by the SharedPtr.
45
46    Example:
47    @code
48    int myStaticFunction(int value)                         // Definition of a static function
49    {
50        return (value * 2);                                 // Return the double of the value
51    }
52
53    FunctorPtr functor = createFunctor(&myStaticFunction);  // Create a Functor
54
55    int result = (*functor)(5);                             // Calls the functor with value = 5, result == 10
56
57    int result = (*functor)("7");                           // Calls the functor with a string which is converted to an integer, result == 14
58    @endcode
59
60    Functors can also be used if you work with member-functions. In this case createFunctor()
61    returns an instance of orxonox::FunctorMemberPtr - this allows you to define the object
62    that will be used to call the function.
63
64    Example:
65    @code
66    class MyClass                                                   // Define a class
67    {
68        public:
69            MyClass(const std::string& text)                        // Constructor
70            {
71                this->text_ = text;
72            }
73
74            bool contains(const std::string& word)                  // Function that searches for "word" in "text"
75            {
76                return (this->text_.find(word) != std::string::npos);
77            }
78
79        private:
80            std::string text_;                                      // Member variable
81    };
82
83    MyClass* object = new MyClass("Hello World");                   // Create an object of type MyClass and set its text to "Hello World"
84
85    FunctorPtr functor = createFunctor(&MyClass:contains, object);  // Create a Functor (note the object!)
86
87    bool result = (*functor)("World");                              // result == true
88    bool result = (*functor)("test");                               // result == false
89    @endcode
90
91    Instead of assigning the object directly to the functor when creating it, you can also define
92    it at any later point or when you call the functor. Note however that this works only with
93    orxonox::FunctorMember.
94
95    @code
96    MyClass* object1 = new MyClass("Hello World");                  // Create an object
97    MyClass* object2 = new MyClass("this is a test");               // Create another object
98
99    FunctorMemberPtr functor = createFunctor(&MyClass:contains);    // Create a FunctorMember (note: no object this time)
100
101    bool result = (*functor)("World");                              // result == false and an error: "Error: Can't execute FunctorMember, no object set."
102
103    bool result = (*functor)(object1, "World");                     // result == true
104    bool result = (*functor)(object1, "test");                      // result == false
105    bool result = (*functor)(object2, "test");                      // result == true
106
107    functor->setObject(object1);                                    // Assign an object to the FunctorMember
108
109    bool result = (*functor)("World");                              // result == true (no error this time, because the object was set using setObject())
110    @endcode
111*/
112
113#ifndef _Functor_H__
114#define _Functor_H__
115
116#include <typeinfo>
117
118#include "core/CorePrereqs.h"
119
120#include "util/Debug.h"
121#include "util/MultiType.h"
122#include "core/OrxonoxClass.h"
123#include "FunctorPtr.h"
124
125namespace orxonox
126{
127    const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;   ///< The maximum number of parameters of a function that is supported by Functor
128
129    namespace detail
130    {
131        template <class T>
132        inline std::string _typeToString() { return "unknown"; }
133
134        template <> inline std::string _typeToString<void>()               { return "void"; }
135        template <> inline std::string _typeToString<int>()                { return "int"; }
136        template <> inline std::string _typeToString<unsigned int>()       { return "uint"; }
137        template <> inline std::string _typeToString<char>()               { return "char"; }
138        template <> inline std::string _typeToString<unsigned char>()      { return "uchar"; }
139        template <> inline std::string _typeToString<short>()              { return "short"; }
140        template <> inline std::string _typeToString<unsigned short>()     { return "ushort"; }
141        template <> inline std::string _typeToString<long>()               { return "long"; }
142        template <> inline std::string _typeToString<unsigned long>()      { return "ulong"; }
143        template <> inline std::string _typeToString<long long>()          { return "longlong"; }
144        template <> inline std::string _typeToString<unsigned long long>() { return "ulonglong"; }
145        template <> inline std::string _typeToString<float>()              { return "float"; }
146        template <> inline std::string _typeToString<double>()             { return "double"; }
147        template <> inline std::string _typeToString<long double>()        { return "longdouble"; }
148        template <> inline std::string _typeToString<bool>()               { return "bool"; }
149        template <> inline std::string _typeToString<std::string>()        { return "string"; }
150        template <> inline std::string _typeToString<Vector2>()            { return "Vector2"; }
151        template <> inline std::string _typeToString<Vector3>()            { return "Vector3"; }
152        template <> inline std::string _typeToString<Quaternion>()         { return "Quaternion"; }
153        template <> inline std::string _typeToString<ColourValue>()        { return "ColourValue"; }
154        template <> inline std::string _typeToString<Radian>()             { return "Radian"; }
155        template <> inline std::string _typeToString<Degree>()             { return "Degree"; }
156    }
157
158    /// Returns the name of type @a T as string.
159    template <class T>
160    inline std::string typeToString() { return detail::_typeToString<typename Loki::TypeTraits<T>::UnqualifiedReferredType>(); }
161
162    /**
163        @brief The Functor classes are used to wrap function pointers.
164
165        Function-pointers in C++ have a pretty complicated syntax and you can't store
166        and call them unless you know the exact type. A Functor can be used to wrap
167        a function-pointer and to store it independent of its type. You can also call
168        it independently of its parameters by passing the arguments as MultiType. They
169        are converted automatically to the right type.
170
171        Functor is a pure virtual base class.
172
173        @see See @ref FunctorExample "Functor.h" for some examples.
174    */
175    class _CoreExport Functor
176    {
177        public:
178            struct Type
179            {
180                /// Defines the type of a function (static or member)
181                enum Enum
182                {
183                    Static,
184                    Member
185                };
186            };
187
188        public:
189            virtual ~Functor() {}
190
191            /// Calls the function-pointer with up to five arguments. In case of a member-function, the assigned object-pointer is used to call the function. @return Returns the return-value of the function (if any; MT_Type::Null otherwise)
192            virtual MultiType operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
193
194            /// Creates a new instance of Functor with the same values like this (used instead of a copy-constructor)
195            virtual FunctorPtr clone() = 0;
196
197            /// Returns the type of the function: static or member.
198            virtual Type::Enum getType() const = 0;
199            /// Returns the number of parameters of the function.
200            virtual unsigned int getParamCount() const = 0;
201            /// Returns true if the function has a return-value.
202            virtual bool hasReturnvalue() const = 0;
203
204            /// Returns the type-name of the parameter with given index (the first parameter has index 0).
205            virtual std::string getTypenameParam(unsigned int index) const = 0;
206            /// Returns the type-name of the return-value.
207            virtual std::string getTypenameReturnvalue() const = 0;
208
209            /// Converts a given argument to the type of the parameter with given index (the first parameter has index 0).
210            virtual void evaluateArgument(unsigned int index, MultiType& argument) const = 0;
211
212            /// Assigns an object-pointer to the functor which is used to execute a member-function.
213            virtual void setRawObjectPointer(void* object) = 0;
214            /// Returns the object-pointer.
215            virtual void* getRawObjectPointer() const = 0;
216
217            /// Enables or disables the safe mode which causes the functor to change the object pointer to NULL if the object is deleted (only member functors).
218            virtual void setSafeMode(bool bSafeMode) = 0;
219
220            /// Returns the full identifier of the function-pointer which is defined as typeid(@a F), where @a F is the type of the stored function-pointer. Used to compare functors.
221            virtual const std::type_info& getFullIdentifier() const = 0;
222            /// Returns an identifier of the header of the function (doesn't include the function's class). Used to compare functors.
223            virtual const std::type_info& getHeaderIdentifier() const = 0;
224            /// Returns an identifier of the header of the function (doesn't include the function's class), but regards only the first @a params parameters. Used to compare functions if an Executor provides default-values for the other parameters.
225            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0;
226    };
227
228    /**
229        @brief FunctorMember is a child class of Functor and expands it with an object-pointer, that
230        is used for member-functions, as well as an overloaded execution operator.
231
232        @param O The type of the function's class (or void if it's a static function)
233
234        Note that FunctorMember is also used for static functions, but with T = void. FunctorStatic
235        is a typedef of FunctorMember<void>. The void* object-pointer is ignored in this case.
236
237        @see See @ref FunctorExample "Functor.h" for some examples.
238    */
239    template <class O>
240    class FunctorMember : public Functor, public DestructionListener
241    {
242        public:
243            /// Constructor: Stores the object-pointer.
244            FunctorMember(O* object = 0) : object_(object), bSafeMode_(false) {}
245            virtual ~FunctorMember() { if (this->bSafeMode_) { this->unregisterObject(this->object_); } }
246            virtual ~FunctorMember() {}
247
248            /// Calls the function-pointer with up to five arguments and an object. In case of a static-function, the object can be NULL. @return Returns the return-value of the function (if any; MT_Type::Null otherwise)
249            virtual MultiType operator()(O* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
250
251            // see Functor::operator()()
252            MultiType operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null)
253            {
254                // call the function if an object was assigned
255                if (this->object_)
256                    return (*this)(this->object_, param1, param2, param3, param4, param5);
257                else
258                {
259                    COUT(1) << "Error: Can't execute FunctorMember, no object set." << std::endl;
260                    return MT_Type::Null;
261                }
262            }
263
264            // see Functor::getType()
265            inline Functor::Type::Enum getType() const
266                { return Functor::Type::Member; }
267
268            /// Assigns an object-pointer to the functor which is used to execute a member-function.
269            inline void setObject(O* object)
270            {
271                if (this->bSafeMode_ && object != this->object_)
272                {
273                    this->unregisterObject(this->object_);
274                    this->registerObject(object);
275                }
276                this->object_ = object;
277            }
278            /// Returns the object-pointer.
279            inline O* getObject() const
280                { return this->object_; }
281
282            // see Functor::setRawObjectPointer()
283            inline void setRawObjectPointer(void* object)
284                { this->setObject((O*)object); }
285            // see Functor::getRawObjectPointer()
286            inline void* getRawObjectPointer() const
287                { return this->object_; }
288
289            // see Functor::setSafeMode()
290            inline void setSafeMode(bool bSafeMode)
291            {
292                if (bSafeMode == this->bSafeMode_)
293                    return;
294
295                this->bSafeMode_ = bSafeMode;
296
297                if (bSafeMode)
298                    this->registerObject(this->object_);
299                else
300                    this->unregisterObject(this->object_);
301            }
302
303        protected:
304            /// Casts the object and registers as destruction listener.
305            inline void registerObject(O* object)
306                { OrxonoxClass* base = dynamic_cast<OrxonoxClass*>(object); if (base) { this->registerAsDestructionListener(base); } }
307            /// Casts the object and unregisters as destruction listener.
308            inline void unregisterObject(O* object)
309                { OrxonoxClass* base = dynamic_cast<OrxonoxClass*>(object); if (base) { this->unregisterAsDestructionListener(base); } }
310
311            /// Will be called by OrxonoxClass::~OrxonoxClass() if the stored object is deleted and the Functor is in safe mode.
312            inline void objectDeleted()
313                { this->object_ = 0; }
314
315            O* object_;     ///< The stored object-pointer, used to execute a member-function (or NULL for static functions)
316            bool bSafeMode_; ///< If true, the functor is in safe mode and registers itself as listener at the object and changes the pointer to NULL if the object is deleted
317    };
318
319    /// Specialization of FunctorMember with @a T = void.
320    template <>
321    class FunctorMember<void> : public Functor
322    {
323        public:
324            /// Constructor: Stores the object-pointer.
325            FunctorMember(void* object = 0) {}
326
327            /// Calls the function-pointer with up to five arguments and an object. In case of a static-function, the object can be NULL. @return Returns the return-value of the function (if any; MT_Type::Null otherwise)
328            virtual MultiType operator()(void* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null) = 0;
329
330            // see Functor::operator()()
331            MultiType operator()(const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null)
332            {
333                return (*this)((void*)0, param1, param2, param3, param4, param5);
334            }
335
336            // see Functor::getType()
337            inline Functor::Type::Enum getType() const
338                { return Functor::Type::Static; }
339
340            // see Functor::setRawObjectPointer()
341            inline void setRawObjectPointer(void*)
342                { COUT(2) << "Warning: Can't assign an object pointer to a static functor" << std::endl; }
343            // see Functor::getRawObjectPointer()
344            inline void* getRawObjectPointer() const
345                { return 0; }
346
347            // see Functor::setSafeMode()
348            inline void setSafeMode(bool) {}
349    };
350
351    /// FunctorStatic is just a typedef of FunctorMember with @a T = void.
352    typedef FunctorMember<void> FunctorStatic;
353
354    /**
355        @brief FunctorPointer is a child class of FunctorMember and expands it with a function-pointer.
356        @param F The type of the function-pointer
357        @param O The type of the function's class (or void if it's a static function)
358
359        The template FunctorPointer has an additional template parameter that defines the type
360        of the function-pointer. This can be handy if you want to get or set the function-pointer.
361        You can then use a static_cast to cast a Functor to FunctorPointer if you know the type
362        of the function-pointer.
363
364        However FunctorPointer is not aware of the types of the different parameters or the
365        return value.
366    */
367    template <class F, class O = void>
368    class FunctorPointer : public FunctorMember<O>
369    {
370        public:
371            /// Constructor: Initializes the base class and stores the function-pointer.
372            FunctorPointer(F functionPointer, O* object = 0) : FunctorMember<O>(object), functionPointer_(functionPointer) {}
373
374            /// Changes the function-pointer.
375            inline void setFunction(F functionPointer)
376                { this->functionPointer_ = functionPointer; }
377            /// Returns the function-pointer.
378            inline F getFunction() const
379                { return this->functionPointer_; }
380
381            // see Functor::getFullIdentifier()
382            const std::type_info& getFullIdentifier() const
383                { return typeid(F); }
384
385        protected:
386            F functionPointer_;     ///< The stored function-pointer
387    };
388
389    namespace detail
390    {
391        // Helper class to get the type of the function pointer with the given class, parameters, return-value, and constness
392        template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer                                            { typedef R (O::*Type)(P1, P2, P3, P4, P5); };
393        template <class R, class O, class P1, class P2, class P3, class P4, class P5>               struct FunctionPointer<R, O, false, P1, P2, P3, P4, P5>           { typedef R (O::*Type)(P1, P2, P3, P4, P5); };
394        template <class R, class O, class P1, class P2, class P3, class P4>                         struct FunctionPointer<R, O, false, P1, P2, P3, P4, void>         { typedef R (O::*Type)(P1, P2, P3, P4); };
395        template <class R, class O, class P1, class P2, class P3>                                   struct FunctionPointer<R, O, false, P1, P2, P3, void, void>       { typedef R (O::*Type)(P1, P2, P3); };
396        template <class R, class O, class P1, class P2>                                             struct FunctionPointer<R, O, false, P1, P2, void, void, void>     { typedef R (O::*Type)(P1, P2); };
397        template <class R, class O, class P1>                                                       struct FunctionPointer<R, O, false, P1, void, void, void, void>   { typedef R (O::*Type)(P1); };
398        template <class R, class O>                                                                 struct FunctionPointer<R, O, false, void, void, void, void, void> { typedef R (O::*Type)(); };
399        template <class R, class O, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer<R, O, true, P1, P2, P3, P4, P5>           { typedef R (O::*Type)(P1, P2, P3, P4, P5) const; };
400        template <class R, class O, class P1, class P2, class P3, class P4>           struct FunctionPointer<R, O, true, P1, P2, P3, P4, void>         { typedef R (O::*Type)(P1, P2, P3, P4) const; };
401        template <class R, class O, class P1, class P2, class P3>                     struct FunctionPointer<R, O, true, P1, P2, P3, void, void>       { typedef R (O::*Type)(P1, P2, P3) const; };
402        template <class R, class O, class P1, class P2>                               struct FunctionPointer<R, O, true, P1, P2, void, void, void>     { typedef R (O::*Type)(P1, P2) const; };
403        template <class R, class O, class P1>                                         struct FunctionPointer<R, O, true, P1, void, void, void, void>   { typedef R (O::*Type)(P1) const; };
404        template <class R, class O>                                                   struct FunctionPointer<R, O, true, void, void, void, void, void> { typedef R (O::*Type)() const; };
405        template <class R, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer<R, void, false, P1, P2, P3, P4, P5>           { typedef R (*Type)(P1, P2, P3, P4, P5); };
406        template <class R, class P1, class P2, class P3, class P4>           struct FunctionPointer<R, void, false, P1, P2, P3, P4, void>         { typedef R (*Type)(P1, P2, P3, P4); };
407        template <class R, class P1, class P2, class P3>                     struct FunctionPointer<R, void, false, P1, P2, P3, void, void>       { typedef R (*Type)(P1, P2, P3); };
408        template <class R, class P1, class P2>                               struct FunctionPointer<R, void, false, P1, P2, void, void, void>     { typedef R (*Type)(P1, P2); };
409        template <class R, class P1>                                         struct FunctionPointer<R, void, false, P1, void, void, void, void>   { typedef R (*Type)(P1); };
410        template <class R>                                                   struct FunctionPointer<R, void, false, void, void, void, void, void> { typedef R (*Type)(); };
411
412        // Helper class, used to call a function-pointer with a given object and parameters and to return its return-value (if available)
413        template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller                                              { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3, param4, param5); } };
414        template <class R, class O, bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<R, O, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3, param4); } };
415        template <class R, class O, bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<R, O, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3); } };
416        template <class R, class O, bool isconst, class P1, class P2>                               struct FunctorCaller<R, O, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2); } };
417        template <class R, class O, bool isconst, class P1>                                         struct FunctorCaller<R, O, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, void, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1); } };
418        template <class R, class O, bool isconst>                                                   struct FunctorCaller<R, O, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, void, void, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(); } };
419        template <class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller<void, O, isconst, P1, P2, P3, P4, P5>           { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2, param3, param4, param5); return MT_Type::Null; } };
420        template <class O, bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<void, O, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, P3, P4, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2, param3, param4); return MT_Type::Null; } };
421        template <class O, bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<void, O, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, P3, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2, param3); return MT_Type::Null; } };
422        template <class O, bool isconst, class P1, class P2>                               struct FunctorCaller<void, O, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2); return MT_Type::Null; } };
423        template <class O, bool isconst, class P1>                                         struct FunctorCaller<void, O, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, void, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1); return MT_Type::Null; } };
424        template <class O, bool isconst>                                                   struct FunctorCaller<void, O, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, void, void, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(); return MT_Type::Null; } };
425        template <class R, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller<R, void, isconst, P1, P2, P3, P4, P5>           { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, P3, P4, P5>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2, param3, param4, param5); } };
426        template <class R, bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<R, void, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, P3, P4, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2, param3, param4); } };
427        template <class R, bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<R, void, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, P3, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2, param3); } };
428        template <class R, bool isconst, class P1, class P2>                               struct FunctorCaller<R, void, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2); } };
429        template <class R, bool isconst, class P1>                                         struct FunctorCaller<R, void, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1); } };
430        template <class R, bool isconst>                                                   struct FunctorCaller<R, void, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, void, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(); } };
431        template <bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller<void, void, isconst, P1, P2, P3, P4, P5>           { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, P3, P4, P5>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2, param3, param4, param5); return MT_Type::Null; } };
432        template <bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<void, void, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, P3, P4, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2, param3, param4); return MT_Type::Null; } };
433        template <bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<void, void, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, P3, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2, param3); return MT_Type::Null; } };
434        template <bool isconst, class P1, class P2>                               struct FunctorCaller<void, void, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2); return MT_Type::Null; } };
435        template <bool isconst, class P1>                                         struct FunctorCaller<void, void, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1); return MT_Type::Null; } };
436        template <bool isconst>                                                   struct FunctorCaller<void, void, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, void, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(); return MT_Type::Null; } };
437
438        // Helper class, used to identify the header of a function-pointer (independent of its class)
439        template <class R, class P1, class P2, class P3, class P4, class P5>
440        struct FunctorHeaderIdentifier
441        {};
442
443        // Helper class to determine if a function has a returnvalue
444        template <class T>
445        struct FunctorHasReturnvalue
446        { enum { result = true }; };
447        template <>
448        struct FunctorHasReturnvalue<void>
449        { enum { result = false }; };
450
451        // Helper class to count the number of parameters
452        template <class P1, class P2, class P3, class P4, class P5>
453        struct FunctorParamCount
454        { enum { result = 5 }; };
455        template <class P1, class P2, class P3, class P4>
456        struct FunctorParamCount<P1, P2, P3, P4, void>
457        { enum { result = 4 }; };
458        template <class P1, class P2, class P3>
459        struct FunctorParamCount<P1, P2, P3, void, void>
460        { enum { result = 3 }; };
461        template <class P1, class P2>
462        struct FunctorParamCount<P1, P2, void, void, void>
463        { enum { result = 2 }; };
464        template <class P1>
465        struct FunctorParamCount<P1, void, void, void, void>
466        { enum { result = 1 }; };
467        template <>
468        struct FunctorParamCount<void, void, void, void, void>
469        { enum { result = 0 }; };
470    }
471
472    /**
473        @brief FunctorTemplate is a child class of FunctorPointer and implements all functions
474        that need to know the exact types of the parameters, return-value, and class.
475
476        @param R The type of the return-value of the function
477        @param O The class of the function
478        @param isconst True if the function is a const member-function
479        @param P1 The type of the first parameter
480        @param P2 The type of the second parameter
481        @param P3 The type of the third parameter
482        @param P4 The type of the fourth parameter
483        @param P5 The type of the fifth parameter
484
485        This template has many parameters and is usually not used directly. It is created by
486        createFunctor(), but only the base-classes Functor, FunctorMember, and FunctorPointer
487        are used directly. It implements all the virtual functions that are declared by its
488        base classes.
489
490        All template arguments can be void.
491    */
492    template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5>
493    class FunctorTemplate : public FunctorPointer<typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type, O>
494    {
495        public:
496            /// Constructor: Initializes the base class.
497            FunctorTemplate(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object = 0) : FunctorPointer<typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type, O>(functionPointer, object) {}
498
499            // see FunctorMember::operator()()
500            MultiType operator()(O* object, const MultiType& param1 = MT_Type::Null, const MultiType& param2 = MT_Type::Null, const MultiType& param3 = MT_Type::Null, const MultiType& param4 = MT_Type::Null, const MultiType& param5 = MT_Type::Null)
501            {
502                return detail::FunctorCaller<R, O, isconst, P1, P2, P3, P4, P5>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);
503            }
504
505            // see Functor::clone()
506            FunctorPtr clone()
507            {
508                return new FunctorTemplate(*this);
509            }
510
511            // see Functor::evaluateArgument()
512            void evaluateArgument(unsigned int index, MultiType& argument) const
513            {
514                switch (index)
515                {
516                    case 0: argument.convert<P1>(); break;
517                    case 1: argument.convert<P2>(); break;
518                    case 2: argument.convert<P3>(); break;
519                    case 3: argument.convert<P4>(); break;
520                    case 4: argument.convert<P5>(); break;
521                }
522            }
523
524            // see Functor::getParamCount()
525            unsigned int getParamCount() const
526            {
527                return detail::FunctorParamCount<P1, P2, P3, P4, P5>::result;
528            }
529
530            // see Functor::hasReturnvalue()
531            bool hasReturnvalue() const
532            {
533                return detail::FunctorHasReturnvalue<R>::result;
534            }
535
536            // see Functor::getTypenameParam()
537            std::string getTypenameParam(unsigned int index) const
538            {
539                switch (index)
540                {
541                    case 0:  return typeToString<P1>();
542                    case 1:  return typeToString<P2>();
543                    case 2:  return typeToString<P3>();
544                    case 3:  return typeToString<P4>();
545                    case 4:  return typeToString<P5>();
546                    default: return "";
547                }
548            }
549
550            // see Functor::getTypenameReturnvalue()
551            std::string getTypenameReturnvalue() const
552            {
553                return typeToString<R>();
554            }
555
556            // see Functor::getHeaderIdentifier()
557            const std::type_info& getHeaderIdentifier() const
558            {
559                return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, P5>);
560            }
561
562            // see Functor::getHeaderIdentifier(unsigned int)
563            const std::type_info& getHeaderIdentifier(unsigned int params) const
564            {
565                switch (params)
566                {
567                    case 0:  return typeid(detail::FunctorHeaderIdentifier<R, void, void, void, void, void>);
568                    case 1:  return typeid(detail::FunctorHeaderIdentifier<R, P1, void, void, void, void>);
569                    case 2:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, void, void, void>);
570                    case 3:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, void, void>);
571                    case 4:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, void>);
572                    default: return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, P5>);
573                }
574            }
575    };
576
577    template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5), OO* object) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
578    template <class R, class O, class OO, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4), OO* object)     { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
579    template <class R, class O, class OO, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3), OO* object)         { return new FunctorTemplate<R, O, false, P1, P2, P3, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
580    template <class R, class O, class OO, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2), OO* object)             { return new FunctorTemplate<R, O, false, P1, P2, void, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
581    template <class R, class O, class OO, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1), OO* object)                 { return new FunctorTemplate<R, O, false, P1, void, void, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
582    template <class R, class O, class OO>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(), OO* object)                   { return new FunctorTemplate<R, O, false, void, void, void, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
583    template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const, OO* object) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
584    template <class R, class O, class OO, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const, OO* object)     { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
585    template <class R, class O, class OO, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const, OO* object)         { return new FunctorTemplate<R, O, true, P1, P2, P3, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
586    template <class R, class O, class OO, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const, OO* object)             { return new FunctorTemplate<R, O, true, P1, P2, void, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
587    template <class R, class O, class OO, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const, OO* object)                 { return new FunctorTemplate<R, O, true, P1, void, void, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
588    template <class R, class O, class OO>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const, OO* object)                   { return new FunctorTemplate<R, O, true, void, void, void, void, void>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
589
590    template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
591    template <class R, class O, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4))     { return new FunctorTemplate<R, O, false, P1, P2, P3, P4, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
592    template <class R, class O, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3))         { return new FunctorTemplate<R, O, false, P1, P2, P3, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
593    template <class R, class O, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2))             { return new FunctorTemplate<R, O, false, P1, P2, void, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
594    template <class R, class O, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1))                 { return new FunctorTemplate<R, O, false, P1, void, void, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
595    template <class R, class O>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)())                   { return new FunctorTemplate<R, O, false, void, void, void, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
596    template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const) { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
597    template <class R, class O, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const)     { return new FunctorTemplate<R, O, true, P1, P2, P3, P4, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
598    template <class R, class O, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const)         { return new FunctorTemplate<R, O, true, P1, P2, P3, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
599    template <class R, class O, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const)             { return new FunctorTemplate<R, O, true, P1, P2, void, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
600    template <class R, class O, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const)                 { return new FunctorTemplate<R, O, true, P1, void, void, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
601    template <class R, class O>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const)                   { return new FunctorTemplate<R, O, true, void, void, void, void, void>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
602
603    template <class R, class P1, class P2, class P3, class P4, class P5> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4, P5)) { return new FunctorTemplate<R, void, false, P1, P2, P3, P4, P5>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
604    template <class R, class P1, class P2, class P3, class P4>           inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4))     { return new FunctorTemplate<R, void, false, P1, P2, P3, P4, void>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
605    template <class R, class P1, class P2, class P3>                     inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3))         { return new FunctorTemplate<R, void, false, P1, P2, P3, void, void>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
606    template <class R, class P1, class P2>                               inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2))             { return new FunctorTemplate<R, void, false, P1, P2, void, void, void>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
607    template <class R, class P1>                                         inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1))                 { return new FunctorTemplate<R, void, false, P1, void, void, void, void>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
608    template <class R>                                                   inline FunctorStaticPtr createFunctor(R (*functionPointer)())                   { return new FunctorTemplate<R, void, false, void, void, void, void, void>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
609}
610
611#endif /* _Functor_H__ */
Note: See TracBrowser for help on using the repository browser.