Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v3/src/libraries/core/command/Functor.h @ 11068

Last change on this file since 11068 was 11068, checked in by landauf, 8 years ago

merged remaining commits from cpp11_v2 to cpp11_v3 (for some reason they were not merged in the first attempt)

  • Property svn:eol-style set to native
File size: 33.8 KB
RevLine 
[1505]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
[7401]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
[11054]42    of orxonox::FunctorPtr which is simply a typedef of "std::shared_ptr<Functor>". This
43    means you don't have to delete the Functor after using it, because it is managed
44    by the std::shared_ptr.
[7401]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
[1505]113#ifndef _Functor_H__
114#define _Functor_H__
115
[8729]116#include "core/CorePrereqs.h"
117
[7179]118#include <typeinfo>
119
[8858]120#include "util/Output.h"
[1747]121#include "util/MultiType.h"
[9667]122#include "core/object/Destroyable.h"
[7196]123#include "FunctorPtr.h"
[1505]124
125namespace orxonox
126{
[7401]127    const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;   ///< The maximum number of parameters of a function that is supported by Functor
[1784]128
[7401]129    namespace detail
130    {
131        template <class T>
132        inline std::string _typeToString() { return "unknown"; }
[1505]133
[7401]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    }
[1505]157
[7401]158    /// Returns the name of type @a T as string.
[7212]159    template <class T>
[7401]160    inline std::string typeToString() { return detail::_typeToString<typename Loki::TypeTraits<T>::UnqualifiedReferredType>(); }
[1505]161
[7401]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    */
[1505]175    class _CoreExport Functor
176    {
177        public:
[11068]178            /// Defines the type of a function (static or member)
179            enum class Type
[7188]180            {
[11068]181                Static,
182                Member
[7188]183            };
184
185        public:
[11054]186            virtual ~Functor() = default;
[7851]187
[9550]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; MultiType::Null otherwise)
189            virtual MultiType operator()(const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) = 0;
[1505]190
[7401]191            /// Creates a new instance of Functor with the same values like this (used instead of a copy-constructor)
[7270]192            virtual FunctorPtr clone() = 0;
193
[7401]194            /// Returns the type of the function: static or member.
[11068]195            virtual Type getType() const = 0;
[7401]196            /// Returns the number of parameters of the function.
[7188]197            virtual unsigned int getParamCount() const = 0;
[7401]198            /// Returns true if the function has a return-value.
[7188]199            virtual bool hasReturnvalue() const = 0;
[1505]200
[7401]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.
[7188]204            virtual std::string getTypenameReturnvalue() const = 0;
205
[7401]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;
[1505]208
[7401]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;
[7179]213
[11054]214            /// Enables or disables the safe mode which causes the functor to change the object pointer to nullptr if the object is deleted (only member functors).
[7851]215            virtual void setSafeMode(bool bSafeMode) = 0;
216
[7401]217            /// 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.
[7212]218            virtual const std::type_info& getFullIdentifier() const = 0;
[7401]219            /// Returns an identifier of the header of the function (doesn't include the function's class). Used to compare functors.
[7179]220            virtual const std::type_info& getHeaderIdentifier() const = 0;
[7401]221            /// 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.
[7214]222            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0;
[1505]223    };
224
[7401]225    /**
226        @brief FunctorMember is a child class of Functor and expands it with an object-pointer, that
227        is used for member-functions, as well as an overloaded execution operator.
228
229        @param O The type of the function's class (or void if it's a static function)
230
231        Note that FunctorMember is also used for static functions, but with T = void. FunctorStatic
232        is a typedef of FunctorMember<void>. The void* object-pointer is ignored in this case.
233
234        @see See @ref FunctorExample "Functor.h" for some examples.
235    */
[7212]236    template <class O>
[7851]237    class FunctorMember : public Functor, public DestructionListener
[1505]238    {
239        public:
[7401]240            /// Constructor: Stores the object-pointer.
[11054]241            FunctorMember(O* object = nullptr) : object_(object), bSafeMode_(false) {}
[7851]242            virtual ~FunctorMember() { if (this->bSafeMode_) { this->unregisterObject(this->object_); } }
[1505]243
[11054]244            /// Calls the function-pointer with up to five arguments and an object. In case of a static-function, the object can be nullptr. @return Returns the return-value of the function (if any; MultiType::Null otherwise)
[9550]245            virtual MultiType operator()(O* object, const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) = 0;
[1505]246
[7401]247            // see Functor::operator()()
[11054]248            virtual MultiType operator()(const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) override
[1505]249            {
[7851]250                // call the function if an object was assigned
251                if (this->object_)
[7189]252                    return (*this)(this->object_, param1, param2, param3, param4, param5);
[1505]253                else
254                {
[8858]255                    orxout(internal_error) << "Can't execute FunctorMember, no object set." << endl;
[9550]256                    return MultiType::Null;
[1505]257                }
258            }
259
[7401]260            // see Functor::getType()
[11068]261            virtual inline Functor::Type getType() const override
[7851]262                { return Functor::Type::Member; }
[1505]263
[7401]264            /// Assigns an object-pointer to the functor which is used to execute a member-function.
[7212]265            inline void setObject(O* object)
[7851]266            {
267                if (this->bSafeMode_ && object != this->object_)
268                {
269                    this->unregisterObject(this->object_);
270                    this->registerObject(object);
271                }
272                this->object_ = object;
273            }
[7401]274            /// Returns the object-pointer.
[7212]275            inline O* getObject() const
276                { return this->object_; }
[1505]277
[7401]278            // see Functor::setRawObjectPointer()
[11054]279            virtual inline void setRawObjectPointer(void* object) override
[7851]280                { this->setObject((O*)object); }
[7401]281            // see Functor::getRawObjectPointer()
[11054]282            virtual inline void* getRawObjectPointer() const override
[7212]283                { return this->object_; }
[7179]284
[7851]285            // see Functor::setSafeMode()
[11054]286            virtual inline void setSafeMode(bool bSafeMode) override
[7851]287            {
288                if (bSafeMode == this->bSafeMode_)
289                    return;
290
291                this->bSafeMode_ = bSafeMode;
292
293                if (bSafeMode)
294                    this->registerObject(this->object_);
295                else
296                    this->unregisterObject(this->object_);
297            }
298
[7212]299        protected:
[11054]300            /// Casts the object and registers as destruction listener if the object is a Destroyable.
301            inline void registerObject(Destroyable* object)
302                { this->registerAsDestructionListener(object); }
[7851]303
[11054]304            inline void registerObject(void* object) {}
[7851]305
[11054]306            /// Casts the object and unregisters as destruction listener if the object is a Destroyable.
307            inline void unregisterObject(Destroyable* object)
308                { this->unregisterAsDestructionListener(object); }
309
310            inline void unregisterObject(void* object) {}
311
312            /// Will be called by Destroyable::~Destroyable() if the stored object is a Destroyable and deleted and the Functor is in safe mode.
313            virtual inline void objectDeleted() override
314                { this->object_ = nullptr; }
315
316            O* object_;     ///< The stored object-pointer, used to execute a member-function (or nullptr for static functions)
317            bool bSafeMode_; ///< If true, the functor is in safe mode and registers itself as listener at the object and changes the pointer to nullptr if the object is deleted
[7212]318    };
[7179]319
[7851]320    /// Specialization of FunctorMember with @a T = void.
321    template <>
322    class FunctorMember<void> : public Functor
323    {
324        public:
325            /// Constructor: Stores the object-pointer.
[11054]326            FunctorMember(void* object = nullptr) {}
[7851]327
[11054]328            /// Calls the function-pointer with up to five arguments and an object. In case of a static-function, the object can be nullptr. @return Returns the return-value of the function (if any; MultiType::Null otherwise)
[9550]329            virtual MultiType operator()(void* object, const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) = 0;
[7851]330
331            // see Functor::operator()()
[11054]332            virtual MultiType operator()(const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) override
[7851]333            {
[11054]334                return (*this)((void*)nullptr, param1, param2, param3, param4, param5);
[7851]335            }
336
337            // see Functor::getType()
[11068]338            virtual inline Functor::Type getType() const override
[7851]339                { return Functor::Type::Static; }
340
341            // see Functor::setRawObjectPointer()
[11054]342            virtual inline void setRawObjectPointer(void*) override
[8858]343                { orxout(internal_warning) << "Can't assign an object pointer to a static functor" << endl; }
[7851]344            // see Functor::getRawObjectPointer()
[11054]345            virtual inline void* getRawObjectPointer() const override
346                { return nullptr; }
[7851]347
348            // see Functor::setSafeMode()
[11054]349            virtual inline void setSafeMode(bool) override {}
[7851]350    };
351
[7401]352    /// FunctorStatic is just a typedef of FunctorMember with @a T = void.
[7212]353    typedef FunctorMember<void> FunctorStatic;
[1505]354
[7401]355    /**
[11054]356        @brief FunctorPointer is a child class of FunctorMember and extends it with a function-pointer (or a function-object).
357        @param F The type of the function-pointer (or the function-object)
358        @param O The type of the function's class (or void if it's a static function or a function-object)
[7401]359
360        The template FunctorPointer has an additional template parameter that defines the type
[11054]361        of the function-pointer (or the function-object). This can be handy if you want to get
362        or set the function-pointer (or the function-object). You can then use a static_cast
363        to cast a Functor to FunctorPointer if you know the type of the function.
[7401]364
365        However FunctorPointer is not aware of the types of the different parameters or the
366        return value.
367    */
[7213]368    template <class F, class O = void>
[7212]369    class FunctorPointer : public FunctorMember<O>
370    {
371        public:
[7401]372            /// Constructor: Initializes the base class and stores the function-pointer.
[11054]373            FunctorPointer(F functionPointer, O* object = nullptr) : FunctorMember<O>(object), functionPointer_(functionPointer) {}
[1505]374
[7401]375            /// Changes the function-pointer.
[7212]376            inline void setFunction(F functionPointer)
377                { this->functionPointer_ = functionPointer; }
[7401]378            /// Returns the function-pointer.
[7212]379            inline F getFunction() const
380                { return this->functionPointer_; }
[7179]381
[7212]382        protected:
[7401]383            F functionPointer_;     ///< The stored function-pointer
[7212]384    };
[7179]385
[7212]386    namespace detail
[7179]387    {
[11054]388        // Helper class to get the type of the function-pointer (or the function-object) with the given class, parameters, return-value, and constness
389        template <class F, class R, class O, bool isconst, class... Params> struct FunctionType /* generic type is undefined */;
390        template <         class R, class O,               class... Params> struct FunctionType<void, R, O,    false, Params...> { typedef R (O::*Type)(Params...); };       // spezialization: non-const member function
391        template <         class R, class O,               class... Params> struct FunctionType<void, R, O,    true,  Params...> { typedef R (O::*Type)(Params...) const; }; // spezialization: const member function
392        template <         class R,                        class... Params> struct FunctionType<void, R, void, false, Params...> { typedef R (*Type)(Params...); };          // spezialization: static function
393        template <class F, class R,                        class... Params> struct FunctionType<F,    R, void, false, Params...> { typedef F Type; };                        // spezialization: function object
[7179]394
[11054]395        // Helper class, used to call a function with a given object and parameters and to return its return-value (if available)
396        template <class F, class R, class O, bool isconst, class... Params> struct FunctorCaller /* generic type is undefined */;
397        template <         class R, class O, bool isconst, class... Params> struct FunctorCaller<void, R,    O,    isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, R,    O,    isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { return (object->*functionPointer)(parameters...); } };                  // spezialization: member function with return value
398        template <                  class O, bool isconst, class... Params> struct FunctorCaller<void, void, O,    isconst, Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, void, O,    isconst, Params...>::Type functionPointer, O* object, const Params&... parameters, const UnusedParams&...) { (object->*functionPointer)(parameters...); return MultiType::Null; } }; // spezialization: member function without return value
399        template <         class R,                        class... Params> struct FunctorCaller<void, R,    void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, R,    void, false,   Params...>::Type functionPointer, void*,     const Params&... parameters, const UnusedParams&...) { return (*functionPointer)(parameters...); } };                          // spezialization: static function with return value
400        template <                                         class... Params> struct FunctorCaller<void, void, void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<void, void, void, false,   Params...>::Type functionPointer, void*,     const Params&... parameters, const UnusedParams&...) { (*functionPointer)(parameters...); return MultiType::Null; } };         // spezialization: static function without return value
401        template <class F, class R,                        class... Params> struct FunctorCaller<F,    R,    void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<F,    R,    void, false,   Params...>::Type functor,         void*,     const Params&... parameters, const UnusedParams&...) { return functor(parameters...); } };                                     // spezialization: function object with return value
402        template <class F,                                 class... Params> struct FunctorCaller<F,    void, void, false,   Params...> { template <class... UnusedParams> static inline MultiType call(typename detail::FunctionType<F,    void, void, false,   Params...>::Type functor,         void*,     const Params&... parameters, const UnusedParams&...) { functor(parameters...); return MultiType::Null; } };                    // spezialization: function object without return value
[7179]403
[7401]404        // Helper class to determine if a function has a returnvalue
[7213]405        template <class T>
[7212]406        struct FunctorHasReturnvalue
407        { enum { result = true }; };
408        template <>
409        struct FunctorHasReturnvalue<void>
410        { enum { result = false }; };
[1505]411
[11054]412        // Helper class to determine the N-th parameter of a variadic template (with 0 being the index of the first parameter)
413        template <int n, typename T = void, typename... Other>
414        struct GetNthParamType
415        { typedef typename GetNthParamType<n - 1, Other...>::Type Type; };
416        template <typename T, typename... Other>
417        struct GetNthParamType<0, T, Other...>
418        { typedef T Type; };
419
420        // Helper structs to deduce the first N types of a parameter pack
421        template<class... Types> struct type_list {};
422
423        template <class T1, class... AllTypes>
424        struct make_type_list_helper
425        {
426            template <std::size_t N, class... Types>
427            struct make_type_list_impl : make_type_list_helper<AllTypes...>::template make_type_list_impl<N - 1, Types..., T1> {};
428
429            template <class... Types>
430            struct make_type_list_impl<1u, Types...> : type_list<Types..., T1> {};
431        };
432
433        template <class T1>
434        struct make_type_list_helper<T1>
435        {
436            template <std::size_t N, class... Types>
437            struct make_type_list_impl : type_list<Types..., T1> {};
438        };
439
440        template <std::size_t N, class... Types>
441        struct make_type_list : make_type_list_helper<Types...>::template make_type_list_impl<N> {};
442
443        template <class... Types>
444        struct make_type_list<0u, Types...> : type_list<> {};
445
446        template <std::size_t N>
447        struct make_type_list<N> : type_list<> {};
448
[7212]449        template <>
[11054]450        struct make_type_list<0u> : type_list<> {};
[1505]451    }
452
[7401]453    /**
454        @brief FunctorTemplate is a child class of FunctorPointer and implements all functions
455        that need to know the exact types of the parameters, return-value, and class.
456
[11054]457        @param F the type of the function-object (or void if a function-pointer is used).
[7401]458        @param R The type of the return-value of the function
459        @param O The class of the function
460        @param isconst True if the function is a const member-function
[11054]461        @param Params The types of the parameters
[7401]462
463        This template has many parameters and is usually not used directly. It is created by
464        createFunctor(), but only the base-classes Functor, FunctorMember, and FunctorPointer
465        are used directly. It implements all the virtual functions that are declared by its
466        base classes.
467
468        All template arguments can be void.
469    */
[11054]470    template <class F, class R, class O, bool isconst, class... Params>
471    class FunctorTemplate : public FunctorPointer<typename detail::FunctionType<F, R, O, isconst, Params...>::Type, O>
[7212]472    {
[11054]473        static_assert(sizeof...(Params) <= 5, "Only up to 5 parameters are supported");
474
[7212]475        public:
[7401]476            /// Constructor: Initializes the base class.
[11054]477            FunctorTemplate(typename detail::FunctionType<F, R, O, isconst, Params...>::Type functionPointer, O* object = nullptr) : FunctorPointer<typename detail::FunctionType<F, R, O, isconst, Params...>::Type, O>(functionPointer, object) {}
[1505]478
[7401]479            // see FunctorMember::operator()()
[11054]480            virtual MultiType operator()(O* object, const MultiType& param1 = MultiType::Null, const MultiType& param2 = MultiType::Null, const MultiType& param3 = MultiType::Null, const MultiType& param4 = MultiType::Null, const MultiType& param5 = MultiType::Null) override
[7212]481            {
[11054]482                return detail::FunctorCaller<F, R, O, isconst, Params...>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);
[7212]483            }
[1505]484
[7401]485            // see Functor::clone()
[11054]486            virtual FunctorPtr clone() override
[7270]487            {
[11054]488                return std::make_shared<FunctorTemplate>(*this);
[7270]489            }
490
[7401]491            // see Functor::evaluateArgument()
[11054]492            virtual void evaluateArgument(unsigned int index, MultiType& argument) const override
[7212]493            {
494                switch (index)
495                {
[11054]496                    case 0: argument.convert<typename detail::GetNthParamType<0, Params...>::Type>(); break;
497                    case 1: argument.convert<typename detail::GetNthParamType<1, Params...>::Type>(); break;
498                    case 2: argument.convert<typename detail::GetNthParamType<2, Params...>::Type>(); break;
499                    case 3: argument.convert<typename detail::GetNthParamType<3, Params...>::Type>(); break;
500                    case 4: argument.convert<typename detail::GetNthParamType<4, Params...>::Type>(); break;
[7212]501                }
502            }
[1505]503
[7401]504            // see Functor::getParamCount()
[11054]505            virtual unsigned int getParamCount() const override
[7212]506            {
[11054]507                return sizeof...(Params);
[7212]508            }
[1505]509
[7401]510            // see Functor::hasReturnvalue()
[11054]511            virtual bool hasReturnvalue() const override
[7212]512            {
513                return detail::FunctorHasReturnvalue<R>::result;
514            }
[1505]515
[7401]516            // see Functor::getTypenameParam()
[11054]517            virtual std::string getTypenameParam(unsigned int index) const override
[7212]518            {
[7401]519                switch (index)
[7212]520                {
[11054]521                    case 0:  return typeToString<typename detail::GetNthParamType<0, Params...>::Type>();
522                    case 1:  return typeToString<typename detail::GetNthParamType<1, Params...>::Type>();
523                    case 2:  return typeToString<typename detail::GetNthParamType<2, Params...>::Type>();
524                    case 3:  return typeToString<typename detail::GetNthParamType<3, Params...>::Type>();
525                    case 4:  return typeToString<typename detail::GetNthParamType<4, Params...>::Type>();
[7212]526                    default: return "";
527                }
528            }
[1505]529
[7401]530            // see Functor::getTypenameReturnvalue()
[11054]531            virtual std::string getTypenameReturnvalue() const override
[7212]532            {
533                return typeToString<R>();
534            }
[7179]535
[11054]536            // see Functor::getFullIdentifier()
537            virtual const std::type_info& getFullIdentifier() const override
538            {
539                return typeid(typename detail::FunctionType<void, R, O, isconst, Params...>::Type);
540            }
541
[7401]542            // see Functor::getHeaderIdentifier()
[11054]543            virtual const std::type_info& getHeaderIdentifier() const override
[7212]544            {
[11054]545                return typeid(typename detail::FunctionType<void, R, void, false, Params...>::Type);
[7212]546            }
[7214]547
[7401]548            // see Functor::getHeaderIdentifier(unsigned int)
[11054]549            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const override
[7214]550            {
551                switch (params)
552                {
[11054]553                    case 0:  return this->getTypelistIdentifier(detail::make_type_list<0, Params...>{});
554                    case 1:  return this->getTypelistIdentifier(detail::make_type_list<1, Params...>{});
555                    case 2:  return this->getTypelistIdentifier(detail::make_type_list<2, Params...>{});
556                    case 3:  return this->getTypelistIdentifier(detail::make_type_list<3, Params...>{});
557                    case 4:  return this->getTypelistIdentifier(detail::make_type_list<4, Params...>{});
558                    default: return this->getTypelistIdentifier(detail::make_type_list<5, Params...>{});
[7214]559                }
560            }
[11054]561
562    private:
563            /// Helper function that deduces a parameter pack of types and returns the corresponding identifier
564            template<class... Types>
565            const std::type_info& getTypelistIdentifier(detail::type_list<Types...>) const
566            {
567                return typeid(typename detail::FunctionType<void, R, void, false, Types...>::Type);
568            }
[7212]569    };
[1505]570
571
[11054]572    namespace detail
573    {
574        // Helper functions to deduce types and constness of operator() and return the correct FunctorTemplate
575        template <class F>
576        struct CallableHelper
577        {
578            template <class R, class... Params> static inline FunctorStaticPtr create(const F& functionObject, R(F::*)(Params...))       { return std::make_shared<FunctorTemplate<F, R, void, false, Params...>>(functionObject); }
579            template <class R, class... Params> static inline FunctorStaticPtr create(const F& functionObject, R(F::*)(Params...) const) { return std::make_shared<FunctorTemplate<F, R, void, false, Params...>>(functionObject); } // note: both const and non-const function-objects are treated as static functors with isconst=false.
580        };
581    }
[1505]582
[11054]583    template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...),       OO* object) { return std::make_shared<FunctorTemplate<void, R, O, false, Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
584    template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const, OO* object) { return std::make_shared<FunctorTemplate<void, R, O, true,  Params...>>(functionPointer, object); } ///< Creates a new FunctorMember with the given function-pointer and an assigned object
585
586    template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...))       { return std::make_shared<FunctorTemplate<void, R, O, false, Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
587    template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const) { return std::make_shared<FunctorTemplate<void, R, O, true,  Params...>>(functionPointer); } ///< Creates a new FunctorMember with the given function-pointer
588
589    template <class R, class... Params> inline FunctorStaticPtr createFunctor(R (*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<void, R, void, false, Params...>>(functionPointer); } ///< Creates a new FunctorStatic with the given function-pointer
590
591    /** Take care that this functor does not outlive objects that have been captured by reference in a lambda. */
592    template <class F> inline FunctorStaticPtr createFunctor(const F& functionObject) { return detail::CallableHelper<F>::create(functionObject, &F::operator()); } ///< Creates a new Functor with a callable object
[1505]593}
594
595#endif /* _Functor_H__ */
Note: See TracBrowser for help on using the repository browser.