Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/core/command/Functor.h @ 7588

Last change on this file since 7588 was 7401, checked in by landauf, 14 years ago

merged doc branch back to trunk

  • Property svn:eol-style set to native
File size: 47.2 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 "FunctorPtr.h"
123
124namespace orxonox
125{
126    const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;   ///< The maximum number of parameters of a function that is supported by Functor
127
128    namespace detail
129    {
130        template <class T>
131        inline std::string _typeToString() { return "unknown"; }
132
133        template <> inline std::string _typeToString<void>()               { return "void"; }
134        template <> inline std::string _typeToString<int>()                { return "int"; }
135        template <> inline std::string _typeToString<unsigned int>()       { return "uint"; }
136        template <> inline std::string _typeToString<char>()               { return "char"; }
137        template <> inline std::string _typeToString<unsigned char>()      { return "uchar"; }
138        template <> inline std::string _typeToString<short>()              { return "short"; }
139        template <> inline std::string _typeToString<unsigned short>()     { return "ushort"; }
140        template <> inline std::string _typeToString<long>()               { return "long"; }
141        template <> inline std::string _typeToString<unsigned long>()      { return "ulong"; }
142        template <> inline std::string _typeToString<long long>()          { return "longlong"; }
143        template <> inline std::string _typeToString<unsigned long long>() { return "ulonglong"; }
144        template <> inline std::string _typeToString<float>()              { return "float"; }
145        template <> inline std::string _typeToString<double>()             { return "double"; }
146        template <> inline std::string _typeToString<long double>()        { return "longdouble"; }
147        template <> inline std::string _typeToString<bool>()               { return "bool"; }
148        template <> inline std::string _typeToString<std::string>()        { return "string"; }
149        template <> inline std::string _typeToString<Vector2>()            { return "Vector2"; }
150        template <> inline std::string _typeToString<Vector3>()            { return "Vector3"; }
151        template <> inline std::string _typeToString<Quaternion>()         { return "Quaternion"; }
152        template <> inline std::string _typeToString<ColourValue>()        { return "ColourValue"; }
153        template <> inline std::string _typeToString<Radian>()             { return "Radian"; }
154        template <> inline std::string _typeToString<Degree>()             { return "Degree"; }
155    }
156
157    /// Returns the name of type @a T as string.
158    template <class T>
159    inline std::string typeToString() { return detail::_typeToString<typename Loki::TypeTraits<T>::UnqualifiedReferredType>(); }
160
161    /**
162        @brief The Functor classes are used to wrap function pointers.
163
164        Function-pointers in C++ have a pretty complicated syntax and you can't store
165        and call them unless you know the exact type. A Functor can be used to wrap
166        a function-pointer and to store it independent of its type. You can also call
167        it independently of its parameters by passing the arguments as MultiType. They
168        are converted automatically to the right type.
169
170        Functor is a pure virtual base class.
171
172        @see See @ref FunctorExample "Functor.h" for some examples.
173    */
174    class _CoreExport Functor
175    {
176        public:
177            struct Type
178            {
179                /// Defines the type of a function (static or member)
180                enum Enum
181                {
182                    Static,
183                    Member
184                };
185            };
186
187        public:
188            /// 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)
189            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;
190
191            /// Creates a new instance of Functor with the same values like this (used instead of a copy-constructor)
192            virtual FunctorPtr clone() = 0;
193
194            /// Returns the type of the function: static or member.
195            virtual Type::Enum getType() const = 0;
196            /// Returns the number of parameters of the function.
197            virtual unsigned int getParamCount() const = 0;
198            /// Returns true if the function has a return-value.
199            virtual bool hasReturnvalue() const = 0;
200
201            /// Returns the type-name of the parameter with given index (the first parameter has index 0).
202            virtual std::string getTypenameParam(unsigned int index) const = 0;
203            /// Returns the type-name of the return-value.
204            virtual std::string getTypenameReturnvalue() const = 0;
205
206            /// Converts a given argument to the type of the parameter with given index (the first parameter has index 0).
207            virtual void evaluateArgument(unsigned int index, MultiType& argument) const = 0;
208
209            /// Assigns an object-pointer to the functor which is used to execute a member-function.
210            virtual void setRawObjectPointer(void* object) = 0;
211            /// Returns the object-pointer.
212            virtual void* getRawObjectPointer() const = 0;
213
214            /// 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.
215            virtual const std::type_info& getFullIdentifier() const = 0;
216            /// Returns an identifier of the header of the function (doesn't include the function's class). Used to compare functors.
217            virtual const std::type_info& getHeaderIdentifier() const = 0;
218            /// 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.
219            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0;
220    };
221
222    namespace detail
223    {
224        // helper class to determine if a functor is static or not
225        template <class O>
226        struct FunctorTypeStatic
227        { enum { result = false }; };
228        template <>
229        struct FunctorTypeStatic<void>
230        { enum { result = true }; };
231    }
232
233    /**
234        @brief FunctorMember is a child class of Functor and expands it with an object-pointer, that
235        is used for member-functions, as well as an overloaded execution operator.
236
237        @param O The type of the function's class (or void if it's a static function)
238
239        Note that FunctorMember is also used for static functions, but with T = void. FunctorStatic
240        is a typedef of FunctorMember<void>. The void* object-pointer is ignored in this case.
241
242        @see See @ref FunctorExample "Functor.h" for some examples.
243    */
244    template <class O>
245    class FunctorMember : public Functor
246    {
247        public:
248            /// Constructor: Stores the object-pointer.
249            FunctorMember(O* object = 0) : object_(object) {}
250
251            /// 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)
252            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;
253
254            // see Functor::operator()()
255            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)
256            {
257                // call the function if it is static or if an object was assigned
258                if (detail::FunctorTypeStatic<O>::result || this->object_)
259                    return (*this)(this->object_, param1, param2, param3, param4, param5);
260                else
261                {
262                    COUT(1) << "Error: Can't execute FunctorMember, no object set." << std::endl;
263                    return MT_Type::Null;
264                }
265            }
266
267            // see Functor::getType()
268            Functor::Type::Enum getType() const
269                { return detail::FunctorTypeStatic<O>::result ? Functor::Type::Static : Functor::Type::Member; }
270
271            /// Assigns an object-pointer to the functor which is used to execute a member-function.
272            inline void setObject(O* object)
273                { this->object_ = object;}
274            /// Returns the object-pointer.
275            inline O* getObject() const
276                { return this->object_; }
277
278            // see Functor::setRawObjectPointer()
279            inline void setRawObjectPointer(void* object)
280                { this->object_ = (O*)object; }
281            // see Functor::getRawObjectPointer()
282            inline void* getRawObjectPointer() const
283                { return this->object_; }
284
285        protected:
286            O* object_;     ///< The stored object-pointer, used to execute a member-function (or NULL for static functions)
287    };
288
289    /// FunctorStatic is just a typedef of FunctorMember with @a T = void.
290    typedef FunctorMember<void> FunctorStatic;
291
292    /**
293        @brief FunctorPointer is a child class of FunctorMember and expands it with a function-pointer.
294        @param F The type of the function-pointer
295        @param O The type of the function's class (or void if it's a static function)
296
297        The template FunctorPointer has an additional template parameter that defines the type
298        of the function-pointer. This can be handy if you want to get or set the function-pointer.
299        You can then use a static_cast to cast a Functor to FunctorPointer if you know the type
300        of the function-pointer.
301
302        However FunctorPointer is not aware of the types of the different parameters or the
303        return value.
304    */
305    template <class F, class O = void>
306    class FunctorPointer : public FunctorMember<O>
307    {
308        public:
309            /// Constructor: Initializes the base class and stores the function-pointer.
310            FunctorPointer(F functionPointer, O* object = 0) : FunctorMember<O>(object), functionPointer_(functionPointer) {}
311
312            /// Changes the function-pointer.
313            inline void setFunction(F functionPointer)
314                { this->functionPointer_ = functionPointer; }
315            /// Returns the function-pointer.
316            inline F getFunction() const
317                { return this->functionPointer_; }
318
319            // see Functor::getFullIdentifier()
320            const std::type_info& getFullIdentifier() const
321                { return typeid(F); }
322
323        protected:
324            F functionPointer_;     ///< The stored function-pointer
325    };
326
327    namespace detail
328    {
329        // Helper class to get the type of the function pointer with the given class, parameters, return-value, and constness
330        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); };
331        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); };
332        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); };
333        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); };
334        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); };
335        template <class R, class O, class P1>                                                       struct FunctionPointer<R, O, false, P1, void, void, void, void>   { typedef R (O::*Type)(P1); };
336        template <class R, class O>                                                                 struct FunctionPointer<R, O, false, void, void, void, void, void> { typedef R (O::*Type)(); };
337        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; };
338        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; };
339        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; };
340        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; };
341        template <class R, class O, class P1>                                         struct FunctionPointer<R, O, true, P1, void, void, void, void>   { typedef R (O::*Type)(P1) const; };
342        template <class R, class O>                                                   struct FunctionPointer<R, O, true, void, void, void, void, void> { typedef R (O::*Type)() const; };
343        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); };
344        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); };
345        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); };
346        template <class R, class P1, class P2>                               struct FunctionPointer<R, void, false, P1, P2, void, void, void>     { typedef R (*Type)(P1, P2); };
347        template <class R, class P1>                                         struct FunctionPointer<R, void, false, P1, void, void, void, void>   { typedef R (*Type)(P1); };
348        template <class R>                                                   struct FunctionPointer<R, void, false, void, void, void, void, void> { typedef R (*Type)(); };
349
350        // Helper class, used to call a function-pointer with a given object and parameters and to return its return-value (if available)
351        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); } };
352        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); } };
353        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); } };
354        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); } };
355        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); } };
356        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)(); } };
357        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; } };
358        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; } };
359        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; } };
360        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; } };
361        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; } };
362        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; } };
363        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); } };
364        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); } };
365        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); } };
366        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); } };
367        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); } };
368        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)(); } };
369        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; } };
370        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; } };
371        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; } };
372        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; } };
373        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; } };
374        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; } };
375
376        // Helper class, used to identify the header of a function-pointer (independent of its class)
377        template <class R, class P1, class P2, class P3, class P4, class P5>
378        struct FunctorHeaderIdentifier
379        {};
380
381        // Helper class to determine if a function has a returnvalue
382        template <class T>
383        struct FunctorHasReturnvalue
384        { enum { result = true }; };
385        template <>
386        struct FunctorHasReturnvalue<void>
387        { enum { result = false }; };
388
389        // Helper class to count the number of parameters
390        template <class P1, class P2, class P3, class P4, class P5>
391        struct FunctorParamCount
392        { enum { result = 5 }; };
393        template <class P1, class P2, class P3, class P4>
394        struct FunctorParamCount<P1, P2, P3, P4, void>
395        { enum { result = 4 }; };
396        template <class P1, class P2, class P3>
397        struct FunctorParamCount<P1, P2, P3, void, void>
398        { enum { result = 3 }; };
399        template <class P1, class P2>
400        struct FunctorParamCount<P1, P2, void, void, void>
401        { enum { result = 2 }; };
402        template <class P1>
403        struct FunctorParamCount<P1, void, void, void, void>
404        { enum { result = 1 }; };
405        template <>
406        struct FunctorParamCount<void, void, void, void, void>
407        { enum { result = 0 }; };
408    }
409
410    /**
411        @brief FunctorTemplate is a child class of FunctorPointer and implements all functions
412        that need to know the exact types of the parameters, return-value, and class.
413
414        @param R The type of the return-value of the function
415        @param O The class of the function
416        @param isconst True if the function is a const member-function
417        @param P1 The type of the first parameter
418        @param P2 The type of the second parameter
419        @param P3 The type of the third parameter
420        @param P4 The type of the fourth parameter
421        @param P5 The type of the fifth parameter
422
423        This template has many parameters and is usually not used directly. It is created by
424        createFunctor(), but only the base-classes Functor, FunctorMember, and FunctorPointer
425        are used directly. It implements all the virtual functions that are declared by its
426        base classes.
427
428        All template arguments can be void.
429    */
430    template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5>
431    class FunctorTemplate : public FunctorPointer<typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type, O>
432    {
433        public:
434            /// Constructor: Initializes the base class.
435            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) {}
436
437            // see FunctorMember::operator()()
438            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)
439            {
440                return detail::FunctorCaller<R, O, isconst, P1, P2, P3, P4, P5>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);
441            }
442
443            // see Functor::clone()
444            FunctorPtr clone()
445            {
446                return new FunctorTemplate(*this);
447            }
448
449            // see Functor::evaluateArgument()
450            void evaluateArgument(unsigned int index, MultiType& argument) const
451            {
452                switch (index)
453                {
454                    case 0: argument.convert<P1>(); break;
455                    case 1: argument.convert<P2>(); break;
456                    case 2: argument.convert<P3>(); break;
457                    case 3: argument.convert<P4>(); break;
458                    case 4: argument.convert<P5>(); break;
459                }
460            }
461
462            // see Functor::getParamCount()
463            unsigned int getParamCount() const
464            {
465                return detail::FunctorParamCount<P1, P2, P3, P4, P5>::result;
466            }
467
468            // see Functor::hasReturnvalue()
469            bool hasReturnvalue() const
470            {
471                return detail::FunctorHasReturnvalue<R>::result;
472            }
473
474            // see Functor::getTypenameParam()
475            std::string getTypenameParam(unsigned int index) const
476            {
477                switch (index)
478                {
479                    case 0:  return typeToString<P1>();
480                    case 1:  return typeToString<P2>();
481                    case 2:  return typeToString<P3>();
482                    case 3:  return typeToString<P4>();
483                    case 4:  return typeToString<P5>();
484                    default: return "";
485                }
486            }
487
488            // see Functor::getTypenameReturnvalue()
489            std::string getTypenameReturnvalue() const
490            {
491                return typeToString<R>();
492            }
493
494            // see Functor::getHeaderIdentifier()
495            const std::type_info& getHeaderIdentifier() const
496            {
497                return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, P5>);
498            }
499
500            // see Functor::getHeaderIdentifier(unsigned int)
501            const std::type_info& getHeaderIdentifier(unsigned int params) const
502            {
503                switch (params)
504                {
505                    case 0:  return typeid(detail::FunctorHeaderIdentifier<R, void, void, void, void, void>);
506                    case 1:  return typeid(detail::FunctorHeaderIdentifier<R, P1, void, void, void, void>);
507                    case 2:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, void, void, void>);
508                    case 3:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, void, void>);
509                    case 4:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, void>);
510                    default: return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, P5>);
511                }
512            }
513    };
514
515    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
516    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
517    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
518    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
519    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
520    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
521    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
522    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
523    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
524    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
525    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
526    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
527
528    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
529    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
530    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
531    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
532    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
533    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
534    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
535    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
536    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
537    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
538    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
539    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
540
541    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
542    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
543    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
544    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
545    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
546    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
547}
548
549#endif /* _Functor_H__ */
Note: See TracBrowser for help on using the repository browser.