Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

now it's again possible to use std::type_info instead of type_index

  • Property svn:eol-style set to native
File size: 33.1 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 <array>
119#include <tuple>
120
121#include "util/Output.h"
122#include "util/MultiType.h"
123#include "core/object/Destroyable.h"
124#include "FunctorPtr.h"
125
126namespace orxonox
127{
128    const unsigned int MAX_FUNCTOR_ARGUMENTS = 5;   ///< The maximum number of parameters of a function that is supported by Functor
129
130    namespace detail
131    {
132        template <class T>
133        inline std::string _typeToString() { return "unknown"; }
134
135        template <> inline std::string _typeToString<void>()               { return "void"; }
136        template <> inline std::string _typeToString<int>()                { return "int"; }
137        template <> inline std::string _typeToString<unsigned int>()       { return "uint"; }
138        template <> inline std::string _typeToString<char>()               { return "char"; }
139        template <> inline std::string _typeToString<unsigned char>()      { return "uchar"; }
140        template <> inline std::string _typeToString<short>()              { return "short"; }
141        template <> inline std::string _typeToString<unsigned short>()     { return "ushort"; }
142        template <> inline std::string _typeToString<long>()               { return "long"; }
143        template <> inline std::string _typeToString<unsigned long>()      { return "ulong"; }
144        template <> inline std::string _typeToString<long long>()          { return "longlong"; }
145        template <> inline std::string _typeToString<unsigned long long>() { return "ulonglong"; }
146        template <> inline std::string _typeToString<float>()              { return "float"; }
147        template <> inline std::string _typeToString<double>()             { return "double"; }
148        template <> inline std::string _typeToString<long double>()        { return "longdouble"; }
149        template <> inline std::string _typeToString<bool>()               { return "bool"; }
150        template <> inline std::string _typeToString<std::string>()        { return "string"; }
151        template <> inline std::string _typeToString<Vector2>()            { return "Vector2"; }
152        template <> inline std::string _typeToString<Vector3>()            { return "Vector3"; }
153        template <> inline std::string _typeToString<Quaternion>()         { return "Quaternion"; }
154        template <> inline std::string _typeToString<ColourValue>()        { return "ColourValue"; }
155        template <> inline std::string _typeToString<Radian>()             { return "Radian"; }
156        template <> inline std::string _typeToString<Degree>()             { return "Degree"; }
157    }
158
159    /// Returns the name of type @a T as string.
160    template <class T>
161    inline std::string typeToString() { return detail::_typeToString<typename Loki::TypeTraits<T>::UnqualifiedReferredType>(); }
162
163    /**
164        @brief The Functor classes are used to wrap function pointers.
165
166        Function-pointers in C++ have a pretty complicated syntax and you can't store
167        and call them unless you know the exact type. A Functor can be used to wrap
168        a function-pointer and to store it independent of its type. You can also call
169        it independently of its parameters by passing the arguments as MultiType. They
170        are converted automatically to the right type.
171
172        Functor is a pure virtual base class.
173
174        @see See @ref FunctorExample "Functor.h" for some examples.
175    */
176    class _CoreExport Functor
177    {
178        public:
179            struct Type
180            {
181                /// Defines the type of a function (static or member)
182                enum Enum
183                {
184                    Static,
185                    Member
186                };
187            };
188
189        public:
190            virtual ~Functor() {}
191
192            /// 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)
193            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;
194
195            /// Creates a new instance of Functor with the same values like this (used instead of a copy-constructor)
196            virtual FunctorPtr clone() = 0;
197
198            /// Returns the type of the function: static or member.
199            virtual Type::Enum getType() const = 0;
200            /// Returns the number of parameters of the function.
201            virtual unsigned int getParamCount() const = 0;
202            /// Returns true if the function has a return-value.
203            virtual bool hasReturnvalue() const = 0;
204
205            /// Returns the type-name of the parameter with given index (the first parameter has index 0).
206            virtual std::string getTypenameParam(unsigned int index) const = 0;
207            /// Returns the type-name of the return-value.
208            virtual std::string getTypenameReturnvalue() const = 0;
209
210            /// Converts a given argument to the type of the parameter with given index (the first parameter has index 0).
211            virtual void evaluateArgument(unsigned int index, MultiType& argument) const = 0;
212
213            /// Assigns an object-pointer to the functor which is used to execute a member-function.
214            virtual void setRawObjectPointer(void* object) = 0;
215            /// Returns the object-pointer.
216            virtual void* getRawObjectPointer() const = 0;
217
218            /// 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).
219            virtual void setSafeMode(bool bSafeMode) = 0;
220
221            /// 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.
222            virtual const std::type_info& getFullIdentifier() const = 0;
223            /// Returns an identifier of the header of the function (doesn't include the function's class). Used to compare functors.
224            virtual const std::type_info& getHeaderIdentifier() const = 0;
225            /// 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.
226            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0;
227    };
228
229    /**
230        @brief FunctorMember is a child class of Functor and expands it with an object-pointer, that
231        is used for member-functions, as well as an overloaded execution operator.
232
233        @param O The type of the function's class (or void if it's a static function)
234
235        Note that FunctorMember is also used for static functions, but with T = void. FunctorStatic
236        is a typedef of FunctorMember<void>. The void* object-pointer is ignored in this case.
237
238        @see See @ref FunctorExample "Functor.h" for some examples.
239    */
240    template <class O>
241    class FunctorMember : public Functor, public DestructionListener
242    {
243        public:
244            /// Constructor: Stores the object-pointer.
245            FunctorMember(O* object = nullptr) : object_(object), bSafeMode_(false) {}
246            virtual ~FunctorMember() { if (this->bSafeMode_) { this->unregisterObject(this->object_); } }
247
248            /// 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)
249            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;
250
251            // see Functor::operator()()
252            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
253            {
254                // call the function if an object was assigned
255                if (this->object_)
256                    return (*this)(this->object_, param1, param2, param3, param4, param5);
257                else
258                {
259                    orxout(internal_error) << "Can't execute FunctorMember, no object set." << endl;
260                    return MultiType::Null;
261                }
262            }
263
264            // see Functor::getType()
265            virtual inline Functor::Type::Enum getType() const override
266                { return Functor::Type::Member; }
267
268            /// Assigns an object-pointer to the functor which is used to execute a member-function.
269            inline void setObject(O* object)
270            {
271                if (this->bSafeMode_ && object != this->object_)
272                {
273                    this->unregisterObject(this->object_);
274                    this->registerObject(object);
275                }
276                this->object_ = object;
277            }
278            /// Returns the object-pointer.
279            inline O* getObject() const
280                { return this->object_; }
281
282            // see Functor::setRawObjectPointer()
283            virtual inline void setRawObjectPointer(void* object) override
284                { this->setObject((O*)object); }
285            // see Functor::getRawObjectPointer()
286            virtual inline void* getRawObjectPointer() const override
287                { return this->object_; }
288
289            // see Functor::setSafeMode()
290            virtual inline void setSafeMode(bool bSafeMode) override
291            {
292                if (bSafeMode == this->bSafeMode_)
293                    return;
294
295                this->bSafeMode_ = bSafeMode;
296
297                if (bSafeMode)
298                    this->registerObject(this->object_);
299                else
300                    this->unregisterObject(this->object_);
301            }
302
303        protected:
304            /// Casts the object and registers as destruction listener if the object is a Destroyable.
305            inline void registerObject(Destroyable* object)
306                { this->registerAsDestructionListener(object); }
307
308            inline void registerObject(void* object) {}
309
310            /// Casts the object and unregisters as destruction listener if the object is a Destroyable.
311            inline void unregisterObject(Destroyable* object)
312                { this->unregisterAsDestructionListener(object); }
313
314            inline void unregisterObject(void* object) {}
315
316            /// Will be called by Destroyable::~Destroyable() if the stored object is a Destroyable and deleted and the Functor is in safe mode.
317            virtual inline void objectDeleted() override
318                { this->object_ = nullptr; }
319
320            O* object_;     ///< The stored object-pointer, used to execute a member-function (or nullptr for static functions)
321            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
322    };
323
324    /// Specialization of FunctorMember with @a T = void.
325    template <>
326    class FunctorMember<void> : public Functor
327    {
328        public:
329            /// Constructor: Stores the object-pointer.
330            FunctorMember(void* object = nullptr) {}
331
332            /// 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)
333            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;
334
335            // see Functor::operator()()
336            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
337            {
338                return (*this)((void*)nullptr, param1, param2, param3, param4, param5);
339            }
340
341            // see Functor::getType()
342            virtual inline Functor::Type::Enum getType() const override
343                { return Functor::Type::Static; }
344
345            // see Functor::setRawObjectPointer()
346            virtual inline void setRawObjectPointer(void*) override
347                { orxout(internal_warning) << "Can't assign an object pointer to a static functor" << endl; }
348            // see Functor::getRawObjectPointer()
349            virtual inline void* getRawObjectPointer() const override
350                { return nullptr; }
351
352            // see Functor::setSafeMode()
353            virtual inline void setSafeMode(bool) override {}
354    };
355
356    /// FunctorStatic is just a typedef of FunctorMember with @a T = void.
357    typedef FunctorMember<void> FunctorStatic;
358
359    /**
360        @brief FunctorPointer is a child class of FunctorMember and expands it with a function-pointer.
361        @param F The type of the function-pointer
362        @param O The type of the function's class (or void if it's a static function)
363
364        The template FunctorPointer has an additional template parameter that defines the type
365        of the function-pointer. This can be handy if you want to get or set the function-pointer.
366        You can then use a static_cast to cast a Functor to FunctorPointer if you know the type
367        of the function-pointer.
368
369        However FunctorPointer is not aware of the types of the different parameters or the
370        return value.
371    */
372    template <class F, class O = void>
373    class FunctorPointer : public FunctorMember<O>
374    {
375        public:
376            /// Constructor: Initializes the base class and stores the function-pointer.
377            FunctorPointer(F functionPointer, O* object = nullptr) : FunctorMember<O>(object), functionPointer_(functionPointer) {}
378
379            /// Changes the function-pointer.
380            inline void setFunction(F functionPointer)
381                { this->functionPointer_ = functionPointer; }
382            /// Returns the function-pointer.
383            inline F getFunction() const
384                { return this->functionPointer_; }
385
386            // see Functor::getFullIdentifier()
387            const std::type_info& getFullIdentifier() const
388                { return typeid(F); }
389
390        protected:
391            F functionPointer_;     ///< The stored function-pointer
392    };
393
394    namespace detail
395    {
396        // Helper class to get the type of the function pointer with the given class, parameters, return-value, and constness
397        template <class R, class O, bool isconst, class... Params> struct FunctionPointer                                   { typedef R (O::*Type)(Params...); };
398        template <class R, class O, class... Params>               struct FunctionPointer<R, O, true, Params...>            { typedef R (O::*Type)(Params...) const; };
399        template <class R, class... Params>                        struct FunctionPointer<R, void, false, Params...>        { typedef R (*Type)(Params...); };
400
401        // Helper class, used to call a function-pointer with a given object and parameters and to return its return-value (if available)
402        template <class R, class O, bool isconst, class... Params>         struct FunctorCaller                                        { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, Params...>::Type functionPointer, O* object, const Params&... parameters)    { return (object->*functionPointer)(parameters...); } };
403        template <class O, bool isconst, class... Params>                  struct FunctorCaller<void, O, isconst, Params...>           { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, Params...>::Type functionPointer, O* object, const Params&... parameters) { (object->*functionPointer)(parameters...); return MultiType::Null; } };
404        template <class R, bool isconst, class... Params>                  struct FunctorCaller<R, void, isconst, Params...>           { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, Params...>::Type functionPointer, void*, const Params&... parameters)     { return (*functionPointer)(parameters...); } };
405        template <bool isconst, class... Params>                           struct FunctorCaller<void, void, isconst, Params...>        { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, Params...>::Type functionPointer, void*, const Params&... parameters)  { (*functionPointer)(parameters...); return MultiType::Null; } };
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        //Barebones implementation of (make_)index_sequence for C++11
424        template <std::size_t...> struct index_sequence {};
425
426        template <std::size_t N, std::size_t... Is>
427        struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};
428
429        template <std::size_t... Is>
430        struct make_index_sequence<0u, Is...> : index_sequence<Is...> {};
431
432        //Helper structs to deduce the first N types of a parameter pack
433        template<class... Types> struct type_list {};
434
435        template <class T1, class... AllTypes>
436        struct make_type_list_helper
437        {
438            template <std::size_t N, class... Types>
439            struct make_type_list_impl : make_type_list_helper<AllTypes...>::template make_type_list_impl<N - 1, Types..., T1> {};
440
441            template <class... Types>
442            struct make_type_list_impl<1u, Types...> : type_list<Types..., T1> {};
443        };
444
445        template <class T1>
446        struct make_type_list_helper<T1>
447        {
448            template <std::size_t N, class... Types>
449            struct make_type_list_impl : type_list<Types..., T1> {};
450        };
451
452        template <std::size_t N, class... Types>
453        struct make_type_list : make_type_list_helper<Types...>::template make_type_list_impl<N> {};
454
455        template <class... Types>
456        struct make_type_list<0u, Types...> : type_list<> {};
457
458        template <std::size_t N>
459        struct make_type_list<N> : type_list<> {};
460
461        template <>
462        struct make_type_list<0u> : type_list<> {};
463    }
464
465    /**
466        @brief FunctorTemplate is a child class of FunctorPointer and implements all functions
467        that need to know the exact types of the parameters, return-value, and class.
468
469        @param R The type of the return-value of the function
470        @param O The class of the function
471        @param isconst True if the function is a const member-function
472        @param Params The types of the parameters
473
474        This template has many parameters and is usually not used directly. It is created by
475        createFunctor(), but only the base-classes Functor, FunctorMember, and FunctorPointer
476        are used directly. It implements all the virtual functions that are declared by its
477        base classes.
478
479        All template arguments can be void.
480    */
481    template <class R, class O, bool isconst, class... Params>
482    class FunctorTemplate : public FunctorPointer<typename detail::FunctionPointer<R, O, isconst, Params...>::Type, O>
483    {
484        static_assert(sizeof...(Params) <= 5, "Only up to 5 parameters are supported");
485
486        public:
487            /// Constructor: Initializes the base class.
488            FunctorTemplate(typename detail::FunctionPointer<R, O, isconst, Params...>::Type functionPointer, O* object = nullptr) : FunctorPointer<typename detail::FunctionPointer<R, O, isconst, Params...>::Type, O>(functionPointer, object) {}
489
490            // see FunctorMember::operator()()
491            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
492            {
493                auto multis = std::make_tuple(param1, param2, param3, param4, param5);
494                return callHelper(object, multis, detail::make_index_sequence<sizeof...(Params)>{});
495            }
496
497            // see Functor::clone()
498            virtual FunctorPtr clone() override
499            {
500                return std::make_shared<FunctorTemplate>(*this);
501            }
502
503            // see Functor::evaluateArgument()
504            virtual void evaluateArgument(unsigned int index, MultiType& argument) const override
505            {
506                switch (index)
507                {
508                    case 0: argument.convert<typename detail::GetNthParamType<0, Params...>::Type>(); break;
509                    case 1: argument.convert<typename detail::GetNthParamType<1, Params...>::Type>(); break;
510                    case 2: argument.convert<typename detail::GetNthParamType<2, Params...>::Type>(); break;
511                    case 3: argument.convert<typename detail::GetNthParamType<3, Params...>::Type>(); break;
512                    case 4: argument.convert<typename detail::GetNthParamType<4, Params...>::Type>(); break;
513                }
514            }
515
516            // see Functor::getParamCount()
517            virtual unsigned int getParamCount() const override
518            {
519                return sizeof...(Params);
520            }
521
522            // see Functor::hasReturnvalue()
523            virtual bool hasReturnvalue() const override
524            {
525                return detail::FunctorHasReturnvalue<R>::result;
526            }
527
528            // see Functor::getTypenameParam()
529            virtual std::string getTypenameParam(unsigned int index) const override
530            {
531                switch (index)
532                {
533                    case 0:  return typeToString<typename detail::GetNthParamType<0, Params...>::Type>();
534                    case 1:  return typeToString<typename detail::GetNthParamType<1, Params...>::Type>();
535                    case 2:  return typeToString<typename detail::GetNthParamType<2, Params...>::Type>();
536                    case 3:  return typeToString<typename detail::GetNthParamType<3, Params...>::Type>();
537                    case 4:  return typeToString<typename detail::GetNthParamType<4, Params...>::Type>();
538                    default: return "";
539                }
540            }
541
542            // see Functor::getTypenameReturnvalue()
543            virtual std::string getTypenameReturnvalue() const override
544            {
545                return typeToString<R>();
546            }
547
548            // see Functor::getHeaderIdentifier()
549            virtual const std::type_info& getHeaderIdentifier() const override
550            {
551                return typeid(typename detail::FunctionPointer<R, void, false, Params...>::Type);
552            }
553
554            // see Functor::getHeaderIdentifier(unsigned int)
555            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const override
556            {
557                switch (params)
558                {
559                    case 0:  return this->getTypelistIdentifier(detail::make_type_list<0, Params...>{});
560                    case 1:  return this->getTypelistIdentifier(detail::make_type_list<1, Params...>{});
561                    case 2:  return this->getTypelistIdentifier(detail::make_type_list<2, Params...>{});
562                    case 3:  return this->getTypelistIdentifier(detail::make_type_list<3, Params...>{});
563                    case 4:  return this->getTypelistIdentifier(detail::make_type_list<4, Params...>{});
564                    default: return this->getTypelistIdentifier(detail::make_type_list<5, Params...>{});
565                }
566            }
567
568    private:
569            /// Helper function that extracts index numbers of parameters from a tuple. Needed to call the function pointer with the correct amount of arguments.
570            template<typename Tup, std::size_t... index>
571            MultiType callHelper(O* object, Tup&& tup, detail::index_sequence<index...>)
572            {
573                return detail::FunctorCaller<R, O, isconst, Params...>::call(this->functionPointer_, object, std::get<index>(std::forward<Tup>(tup))...);
574            }
575
576            ///Helper function that deduces a parameter pack of types and returns the corresponding identifier
577            template<class... Types>
578            const std::type_info& getTypelistIdentifier(detail::type_list<Types...>) const
579            {
580                return typeid(typename detail::FunctionPointer<R, void, false, Types...>::Type);
581            }
582    };
583
584
585    /**
586    @brief FunctorCallable is a child class of FunctorTemplate. It stores a callable
587    object (e.g. a lambda or a class with operator()) inside and acts like any
588    other functor. Note that it stores a \em copy of the object, not a reference or a pointer.
589    Take care that this functor does not outlive objects that have been captured by reference
590    in a lambda.
591
592    @param F The type of the callable object
593    @param R The type of the return-value of the function
594    @param isconst True if operator() is const
595    @param Params The types of the parameters
596
597    This template can not be used directly when using lambdas - the type of a lambda
598    is not specified. It can only really be used through the base-class Functor.
599    */
600    template <class F, class R, bool isconst, class... Params>
601    class FunctorCallable : public FunctorTemplate<R, F, isconst, Params...>
602    {
603    public:
604        FunctorCallable(const F& obj): FunctorTemplate<R, F, isconst, Params...>(&F::operator(), &obj_)
605            , obj_(obj)
606        {}
607
608    private:
609        F obj_; ///< The callable object
610    };
611
612    namespace detail
613    {
614        //Helper functions to deduce types and constness of operator() and return the correct FunctorCallable
615        template <class F, class R, class... Params> inline FunctorMemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...) const) { return std::make_shared<FunctorCallable<F, R, true, Params...>>(obj); }
616        template <class F, class R, class... Params> inline FunctorMemberPtr<F> callableHelper(const F& obj, R(F::*func)(Params...)) { return std::make_shared<FunctorCallable<F, R, false, Params...>>(obj); }
617    }
618
619    template <class R, class O, class OO, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...), OO* object) { return std::make_shared<FunctorTemplate<R, O, false, Params...>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
620    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<R, O, true, Params...>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
621
622    template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<R, O, false, Params...>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
623    template <class R, class O, class... Params> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(Params...) const) { return std::make_shared<FunctorTemplate<R, O, true, Params...>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
624
625    template <class R, class... Params> inline FunctorStaticPtr createFunctor(R (*functionPointer)(Params...)) { return std::make_shared<FunctorTemplate<R, void, false, Params...>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
626   
627    template <class F> inline FunctorMemberPtr<F> createFunctor(const F& obj) { return detail::callableHelper(obj, &F::operator()); } ///< Creates a new Functor with a callable object
628}
629
630#endif /* _Functor_H__ */
Note: See TracBrowser for help on using the repository browser.