Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/src/libraries/core/command/Functor.h @ 10986

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

use the existing class 'FunctorPointer' to store the callable object. functors with callable objects (e.g. lambdas) are now treated as static functors.
this also fixes an issue on gcc: because of a bug, gcc was not able to store the function pointer of a lambda's operator() https://gcc.gnu.org/bugzilla/show_bug.cgi?id=51048. storing the whole object is apparently a workaround for this issue.

Note: tests currently fail on MSVC because it doesn't accept std::function as a callable object.

  • Property svn:eol-style set to native
File size: 33.8 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 "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.
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 "core/CorePrereqs.h"
117
118#include <typeinfo>
119
120#include "util/Output.h"
121#include "util/MultiType.h"
122#include "core/object/Destroyable.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; MultiType::Null otherwise)
192            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;
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 nullptr 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 = nullptr) : object_(object), bSafeMode_(false) {}
245            virtual ~FunctorMember() { if (this->bSafeMode_) { this->unregisterObject(this->object_); } }
246
247            /// 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)
248            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;
249
250            // see Functor::operator()()
251            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
252            {
253                // call the function if an object was assigned
254                if (this->object_)
255                    return (*this)(this->object_, param1, param2, param3, param4, param5);
256                else
257                {
258                    orxout(internal_error) << "Can't execute FunctorMember, no object set." << endl;
259                    return MultiType::Null;
260                }
261            }
262
263            // see Functor::getType()
264            virtual inline Functor::Type::Enum getType() const override
265                { return Functor::Type::Member; }
266
267            /// Assigns an object-pointer to the functor which is used to execute a member-function.
268            inline void setObject(O* object)
269            {
270                if (this->bSafeMode_ && object != this->object_)
271                {
272                    this->unregisterObject(this->object_);
273                    this->registerObject(object);
274                }
275                this->object_ = object;
276            }
277            /// Returns the object-pointer.
278            inline O* getObject() const
279                { return this->object_; }
280
281            // see Functor::setRawObjectPointer()
282            virtual inline void setRawObjectPointer(void* object) override
283                { this->setObject((O*)object); }
284            // see Functor::getRawObjectPointer()
285            virtual inline void* getRawObjectPointer() const override
286                { return this->object_; }
287
288            // see Functor::setSafeMode()
289            virtual inline void setSafeMode(bool bSafeMode) override
290            {
291                if (bSafeMode == this->bSafeMode_)
292                    return;
293
294                this->bSafeMode_ = bSafeMode;
295
296                if (bSafeMode)
297                    this->registerObject(this->object_);
298                else
299                    this->unregisterObject(this->object_);
300            }
301
302        protected:
303            /// Casts the object and registers as destruction listener if the object is a Destroyable.
304            inline void registerObject(Destroyable* object)
305                { this->registerAsDestructionListener(object); }
306
307            inline void registerObject(void* object) {}
308
309            /// Casts the object and unregisters as destruction listener if the object is a Destroyable.
310            inline void unregisterObject(Destroyable* object)
311                { this->unregisterAsDestructionListener(object); }
312
313            inline void unregisterObject(void* object) {}
314
315            /// Will be called by Destroyable::~Destroyable() if the stored object is a Destroyable and deleted and the Functor is in safe mode.
316            virtual inline void objectDeleted() override
317                { this->object_ = nullptr; }
318
319            O* object_;     ///< The stored object-pointer, used to execute a member-function (or nullptr for static functions)
320            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
321    };
322
323    /// Specialization of FunctorMember with @a T = void.
324    template <>
325    class FunctorMember<void> : public Functor
326    {
327        public:
328            /// Constructor: Stores the object-pointer.
329            FunctorMember(void* object = nullptr) {}
330
331            /// 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)
332            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;
333
334            // see Functor::operator()()
335            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
336            {
337                return (*this)((void*)nullptr, param1, param2, param3, param4, param5);
338            }
339
340            // see Functor::getType()
341            virtual inline Functor::Type::Enum getType() const override
342                { return Functor::Type::Static; }
343
344            // see Functor::setRawObjectPointer()
345            virtual inline void setRawObjectPointer(void*) override
346                { orxout(internal_warning) << "Can't assign an object pointer to a static functor" << endl; }
347            // see Functor::getRawObjectPointer()
348            virtual inline void* getRawObjectPointer() const override
349                { return nullptr; }
350
351            // see Functor::setSafeMode()
352            virtual inline void setSafeMode(bool) override {}
353    };
354
355    /// FunctorStatic is just a typedef of FunctorMember with @a T = void.
356    typedef FunctorMember<void> FunctorStatic;
357
358    /**
359        @brief FunctorPointer is a child class of FunctorMember and extends it with a function-pointer (or a function-object).
360        @param F The type of the function-pointer (or the function-object)
361        @param O The type of the function's class (or void if it's a static function or a function-object)
362
363        The template FunctorPointer has an additional template parameter that defines the type
364        of the function-pointer (or the function-object). This can be handy if you want to get
365        or set the function-pointer (or the function-object). You can then use a static_cast
366        to cast a Functor to FunctorPointer if you know the type of the function.
367
368        However FunctorPointer is not aware of the types of the different parameters or the
369        return value.
370    */
371    template <class F, class O = void>
372    class FunctorPointer : public FunctorMember<O>
373    {
374        public:
375            /// Constructor: Initializes the base class and stores the function-pointer.
376            FunctorPointer(F functionPointer, O* object = nullptr) : FunctorMember<O>(object), functionPointer_(functionPointer) {}
377
378            /// Changes the function-pointer.
379            inline void setFunction(F functionPointer)
380                { this->functionPointer_ = functionPointer; }
381            /// Returns the function-pointer.
382            inline F getFunction() const
383                { return this->functionPointer_; }
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 (or the function-object) with the given class, parameters, return-value, and constness
392        template <class F, class R, class O, bool isconst, class... Params> struct FunctionType /* generic type is undefined */;
393        template <         class R, class O,               class... Params> struct FunctionType<void, R, O,    false, Params...> { typedef R (O::*Type)(Params...); };       // spezialization: non-const member function
394        template <         class R, class O,               class... Params> struct FunctionType<void, R, O,    true,  Params...> { typedef R (O::*Type)(Params...) const; }; // spezialization: const member function
395        template <         class R,                        class... Params> struct FunctionType<void, R, void, false, Params...> { typedef R (*Type)(Params...); };          // spezialization: static function
396        template <class F, class R,                        class... Params> struct FunctionType<F,    R, void, false, Params...> { typedef F Type; };                        // spezialization: function object
397
398        // Helper class, used to call a function with a given object and parameters and to return its return-value (if available)
399        template <class F, class R, class O, bool isconst, class... Params> struct FunctorCaller /* generic type is undefined */;
400        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
401        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
402        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
403        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
404        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
405        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
406
407        // Helper class to determine if a function has a returnvalue
408        template <class T>
409        struct FunctorHasReturnvalue
410        { enum { result = true }; };
411        template <>
412        struct FunctorHasReturnvalue<void>
413        { enum { result = false }; };
414
415        // Helper class to determine the N-th parameter of a variadic template (with 0 being the index of the first parameter)
416        template <int n, typename T = void, typename... Other>
417        struct GetNthParamType
418        { typedef typename GetNthParamType<n - 1, Other...>::Type Type; };
419        template <typename T, typename... Other>
420        struct GetNthParamType<0, T, Other...>
421        { typedef T Type; };
422
423        //Helper structs to deduce the first N types of a parameter pack
424        template<class... Types> struct type_list {};
425
426        template <class T1, class... AllTypes>
427        struct make_type_list_helper
428        {
429            template <std::size_t N, class... Types>
430            struct make_type_list_impl : make_type_list_helper<AllTypes...>::template make_type_list_impl<N - 1, Types..., T1> {};
431
432            template <class... Types>
433            struct make_type_list_impl<1u, Types...> : type_list<Types..., T1> {};
434        };
435
436        template <class T1>
437        struct make_type_list_helper<T1>
438        {
439            template <std::size_t N, class... Types>
440            struct make_type_list_impl : type_list<Types..., T1> {};
441        };
442
443        template <std::size_t N, class... Types>
444        struct make_type_list : make_type_list_helper<Types...>::template make_type_list_impl<N> {};
445
446        template <class... Types>
447        struct make_type_list<0u, Types...> : type_list<> {};
448
449        template <std::size_t N>
450        struct make_type_list<N> : type_list<> {};
451
452        template <>
453        struct make_type_list<0u> : type_list<> {};
454    }
455
456    /**
457        @brief FunctorTemplate is a child class of FunctorPointer and implements all functions
458        that need to know the exact types of the parameters, return-value, and class.
459
460        @param F the type of the function-object (or void if a function-pointer is used).
461        @param R The type of the return-value of the function
462        @param O The class of the function
463        @param isconst True if the function is a const member-function
464        @param Params The types of the parameters
465
466        This template has many parameters and is usually not used directly. It is created by
467        createFunctor(), but only the base-classes Functor, FunctorMember, and FunctorPointer
468        are used directly. It implements all the virtual functions that are declared by its
469        base classes.
470
471        All template arguments can be void.
472    */
473    template <class F, class R, class O, bool isconst, class... Params>
474    class FunctorTemplate : public FunctorPointer<typename detail::FunctionType<F, R, O, isconst, Params...>::Type, O>
475    {
476        static_assert(sizeof...(Params) <= 5, "Only up to 5 parameters are supported");
477
478        public:
479            /// Constructor: Initializes the base class.
480            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) {}
481
482            // see FunctorMember::operator()()
483            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
484            {
485                return detail::FunctorCaller<F, R, O, isconst, Params...>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);
486            }
487
488            // see Functor::clone()
489            virtual FunctorPtr clone() override
490            {
491                return std::make_shared<FunctorTemplate>(*this);
492            }
493
494            // see Functor::evaluateArgument()
495            virtual void evaluateArgument(unsigned int index, MultiType& argument) const override
496            {
497                switch (index)
498                {
499                    case 0: argument.convert<typename detail::GetNthParamType<0, Params...>::Type>(); break;
500                    case 1: argument.convert<typename detail::GetNthParamType<1, Params...>::Type>(); break;
501                    case 2: argument.convert<typename detail::GetNthParamType<2, Params...>::Type>(); break;
502                    case 3: argument.convert<typename detail::GetNthParamType<3, Params...>::Type>(); break;
503                    case 4: argument.convert<typename detail::GetNthParamType<4, Params...>::Type>(); break;
504                }
505            }
506
507            // see Functor::getParamCount()
508            virtual unsigned int getParamCount() const override
509            {
510                return sizeof...(Params);
511            }
512
513            // see Functor::hasReturnvalue()
514            virtual bool hasReturnvalue() const override
515            {
516                return detail::FunctorHasReturnvalue<R>::result;
517            }
518
519            // see Functor::getTypenameParam()
520            virtual std::string getTypenameParam(unsigned int index) const override
521            {
522                switch (index)
523                {
524                    case 0:  return typeToString<typename detail::GetNthParamType<0, Params...>::Type>();
525                    case 1:  return typeToString<typename detail::GetNthParamType<1, Params...>::Type>();
526                    case 2:  return typeToString<typename detail::GetNthParamType<2, Params...>::Type>();
527                    case 3:  return typeToString<typename detail::GetNthParamType<3, Params...>::Type>();
528                    case 4:  return typeToString<typename detail::GetNthParamType<4, Params...>::Type>();
529                    default: return "";
530                }
531            }
532
533            // see Functor::getTypenameReturnvalue()
534            virtual std::string getTypenameReturnvalue() const override
535            {
536                return typeToString<R>();
537            }
538
539            // see Functor::getFullIdentifier()
540            virtual const std::type_info& getFullIdentifier() const override
541            {
542                return typeid(typename detail::FunctionType<void, R, O, isconst, Params...>::Type);
543            }
544
545            // see Functor::getHeaderIdentifier()
546            virtual const std::type_info& getHeaderIdentifier() const override
547            {
548                return typeid(typename detail::FunctionType<void, R, void, false, Params...>::Type);
549            }
550
551            // see Functor::getHeaderIdentifier(unsigned int)
552            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const override
553            {
554                switch (params)
555                {
556                    case 0:  return this->getTypelistIdentifier(detail::make_type_list<0, Params...>{});
557                    case 1:  return this->getTypelistIdentifier(detail::make_type_list<1, Params...>{});
558                    case 2:  return this->getTypelistIdentifier(detail::make_type_list<2, Params...>{});
559                    case 3:  return this->getTypelistIdentifier(detail::make_type_list<3, Params...>{});
560                    case 4:  return this->getTypelistIdentifier(detail::make_type_list<4, Params...>{});
561                    default: return this->getTypelistIdentifier(detail::make_type_list<5, Params...>{});
562                }
563            }
564
565    private:
566            ///Helper function that deduces a parameter pack of types and returns the corresponding identifier
567            template<class... Types>
568            const std::type_info& getTypelistIdentifier(detail::type_list<Types...>) const
569            {
570                return typeid(typename detail::FunctionType<void, R, void, false, Types...>::Type);
571            }
572    };
573
574
575    namespace detail
576    {
577        //Helper functions to deduce types and constness of operator() and return the correct FunctorCallable
578        template <class F, class R, class... Params> inline FunctorStaticPtr callableHelper(const F& functionObject, R(F::*)(Params...))       { return std::make_shared<FunctorTemplate<F, R, void, false, Params...>>(functionObject); }
579        template <class F, class R, class... Params> inline FunctorStaticPtr callableHelper(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
582    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
583    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
584
585    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
586    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
587
588    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
589
590    /** Take care that this functor does not outlive objects that have been captured by reference in a lambda. */
591    template <class F> inline FunctorStaticPtr createFunctor(const F& functionObject) { return detail::callableHelper(functionObject, &F::operator()); } ///< Creates a new Functor with a callable object
592}
593
594#endif /* _Functor_H__ */
Note: See TracBrowser for help on using the repository browser.