[Orxonox-commit 6219] r10876 - code/branches/cpp11_v2/src/libraries/core/command

muemart at orxonox.net muemart at orxonox.net
Fri Nov 27 16:19:07 CET 2015


Author: muemart
Date: 2015-11-27 16:19:06 +0100 (Fri, 27 Nov 2015)
New Revision: 10876

Modified:
   code/branches/cpp11_v2/src/libraries/core/command/Functor.h
Log:
Use variadic templates for Functor
Had to put on my template hat for this one... The only thing preventing it from supporting more than five parameters is the complete type erasure (see operator())
I also had to use type_index because you can't store type_info, so I changed the other functions too for consistency's sake

Modified: code/branches/cpp11_v2/src/libraries/core/command/Functor.h
===================================================================
--- code/branches/cpp11_v2/src/libraries/core/command/Functor.h	2015-11-27 12:41:26 UTC (rev 10875)
+++ code/branches/cpp11_v2/src/libraries/core/command/Functor.h	2015-11-27 15:19:06 UTC (rev 10876)
@@ -115,7 +115,9 @@
 
 #include "core/CorePrereqs.h"
 
-#include <typeinfo>
+#include <array>
+#include <typeindex>
+#include <tuple>
 
 #include "util/Output.h"
 #include "util/MultiType.h"
@@ -218,11 +220,11 @@
             virtual void setSafeMode(bool bSafeMode) = 0;
 
             /// 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.
-            virtual const std::type_info& getFullIdentifier() const = 0;
+            virtual const std::type_index getFullIdentifier() const = 0;
             /// Returns an identifier of the header of the function (doesn't include the function's class). Used to compare functors.
-            virtual const std::type_info& getHeaderIdentifier() const = 0;
+            virtual const std::type_index getHeaderIdentifier() const = 0;
             /// 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.
-            virtual const std::type_info& getHeaderIdentifier(unsigned int params) const = 0;
+            virtual const std::type_index getHeaderIdentifier(unsigned int params) const = 0;
     };
 
     /**
@@ -378,7 +380,7 @@
                 { return this->functionPointer_; }
 
             // see Functor::getFullIdentifier()
-            const std::type_info& getFullIdentifier() const
+            const std::type_index getFullIdentifier() const
                 { return typeid(F); }
 
         protected:
@@ -388,54 +390,18 @@
     namespace detail
     {
         // Helper class to get the type of the function pointer with the given class, parameters, return-value, and constness
-        template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer                                            { typedef R (O::*Type)(P1, P2, P3, P4, P5); };
-        template <class R, class O, class P1, class P2, class P3, class P4, class P5>               struct FunctionPointer<R, O, false, P1, P2, P3, P4, P5>           { typedef R (O::*Type)(P1, P2, P3, P4, P5); };
-        template <class R, class O, class P1, class P2, class P3, class P4>                         struct FunctionPointer<R, O, false, P1, P2, P3, P4, void>         { typedef R (O::*Type)(P1, P2, P3, P4); };
-        template <class R, class O, class P1, class P2, class P3>                                   struct FunctionPointer<R, O, false, P1, P2, P3, void, void>       { typedef R (O::*Type)(P1, P2, P3); };
-        template <class R, class O, class P1, class P2>                                             struct FunctionPointer<R, O, false, P1, P2, void, void, void>     { typedef R (O::*Type)(P1, P2); };
-        template <class R, class O, class P1>                                                       struct FunctionPointer<R, O, false, P1, void, void, void, void>   { typedef R (O::*Type)(P1); };
-        template <class R, class O>                                                                 struct FunctionPointer<R, O, false, void, void, void, void, void> { typedef R (O::*Type)(); };
-        template <class R, class O, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer<R, O, true, P1, P2, P3, P4, P5>           { typedef R (O::*Type)(P1, P2, P3, P4, P5) const; };
-        template <class R, class O, class P1, class P2, class P3, class P4>           struct FunctionPointer<R, O, true, P1, P2, P3, P4, void>         { typedef R (O::*Type)(P1, P2, P3, P4) const; };
-        template <class R, class O, class P1, class P2, class P3>                     struct FunctionPointer<R, O, true, P1, P2, P3, void, void>       { typedef R (O::*Type)(P1, P2, P3) const; };
-        template <class R, class O, class P1, class P2>                               struct FunctionPointer<R, O, true, P1, P2, void, void, void>     { typedef R (O::*Type)(P1, P2) const; };
-        template <class R, class O, class P1>                                         struct FunctionPointer<R, O, true, P1, void, void, void, void>   { typedef R (O::*Type)(P1) const; };
-        template <class R, class O>                                                   struct FunctionPointer<R, O, true, void, void, void, void, void> { typedef R (O::*Type)() const; };
-        template <class R, class P1, class P2, class P3, class P4, class P5> struct FunctionPointer<R, void, false, P1, P2, P3, P4, P5>           { typedef R (*Type)(P1, P2, P3, P4, P5); };
-        template <class R, class P1, class P2, class P3, class P4>           struct FunctionPointer<R, void, false, P1, P2, P3, P4, void>         { typedef R (*Type)(P1, P2, P3, P4); };
-        template <class R, class P1, class P2, class P3>                     struct FunctionPointer<R, void, false, P1, P2, P3, void, void>       { typedef R (*Type)(P1, P2, P3); };
-        template <class R, class P1, class P2>                               struct FunctionPointer<R, void, false, P1, P2, void, void, void>     { typedef R (*Type)(P1, P2); };
-        template <class R, class P1>                                         struct FunctionPointer<R, void, false, P1, void, void, void, void>   { typedef R (*Type)(P1); };
-        template <class R>                                                   struct FunctionPointer<R, void, false, void, void, void, void, void> { typedef R (*Type)(); };
+        template <class R, class O, bool isconst, class... Params> struct FunctionPointer                                   { typedef R (O::*Type)(Params...); };
+        template <class R, class O, class... Params>               struct FunctionPointer<R, O, true, Params...>            { typedef R (O::*Type)(Params...) const; };
+        template <class R, class... Params>                        struct FunctionPointer<R, void, false, Params...>        { typedef R (*Type)(Params...); };
 
         // Helper class, used to call a function-pointer with a given object and parameters and to return its return-value (if available)
-        template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller                                              { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (object->*functionPointer)(param1, param2, param3, param4, param5); } };
-        template <class R, class O, bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<R, O, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType&) { return (object->*functionPointer)(param1, param2, param3, param4); } };
-        template <class R, class O, bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<R, O, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType&, const MultiType&) { return (object->*functionPointer)(param1, param2, param3); } };
-        template <class R, class O, bool isconst, class P1, class P2>                               struct FunctorCaller<R, O, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, P2, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType&, const MultiType&, const MultiType&) { return (object->*functionPointer)(param1, param2); } };
-        template <class R, class O, bool isconst, class P1>                                         struct FunctorCaller<R, O, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, P1, void, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { return (object->*functionPointer)(param1); } };
-        template <class R, class O, bool isconst>                                                   struct FunctorCaller<R, O, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<R, O, isconst, void, void, void, void, void>::Type functionPointer, O* object, const MultiType&, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { return (object->*functionPointer)(); } };
-        template <class O, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller<void, O, isconst, P1, P2, P3, P4, P5>           { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (object->*functionPointer)(param1, param2, param3, param4, param5); return MultiType::Null; } };
-        template <class O, bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<void, O, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, P3, P4, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType&) { (object->*functionPointer)(param1, param2, param3, param4); return MultiType::Null; } };
-        template <class O, bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<void, O, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, P3, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType&, const MultiType&) { (object->*functionPointer)(param1, param2, param3); return MultiType::Null; } };
-        template <class O, bool isconst, class P1, class P2>                               struct FunctorCaller<void, O, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, P2, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType& param2, const MultiType&, const MultiType&, const MultiType&) { (object->*functionPointer)(param1, param2); return MultiType::Null; } };
-        template <class O, bool isconst, class P1>                                         struct FunctorCaller<void, O, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, P1, void, void, void, void>::Type functionPointer, O* object, const MultiType& param1, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { (object->*functionPointer)(param1); return MultiType::Null; } };
-        template <class O, bool isconst>                                                   struct FunctorCaller<void, O, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<void, O, isconst, void, void, void, void, void>::Type functionPointer, O* object, const MultiType&, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { (object->*functionPointer)(); return MultiType::Null; } };
-        template <class R, bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller<R, void, isconst, P1, P2, P3, P4, P5>           { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, P3, P4, P5>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { return (*functionPointer)(param1, param2, param3, param4, param5); } };
-        template <class R, bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<R, void, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, P3, P4, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType&) { return (*functionPointer)(param1, param2, param3, param4); } };
-        template <class R, bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<R, void, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, P3, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType&, const MultiType&) { return (*functionPointer)(param1, param2, param3); } };
-        template <class R, bool isconst, class P1, class P2>                               struct FunctorCaller<R, void, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, P2, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType&, const MultiType&, const MultiType&) { return (*functionPointer)(param1, param2); } };
-        template <class R, bool isconst, class P1>                                         struct FunctorCaller<R, void, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, P1, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { return (*functionPointer)(param1); } };
-        template <class R, bool isconst>                                                   struct FunctorCaller<R, void, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<R, void, isconst, void, void, void, void, void>::Type functionPointer, void*, const MultiType&, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { return (*functionPointer)(); } };
-        template <bool isconst, class P1, class P2, class P3, class P4, class P5> struct FunctorCaller<void, void, isconst, P1, P2, P3, P4, P5>           { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, P3, P4, P5>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType& param5) { (*functionPointer)(param1, param2, param3, param4, param5); return MultiType::Null; } };
-        template <bool isconst, class P1, class P2, class P3, class P4>           struct FunctorCaller<void, void, isconst, P1, P2, P3, P4, void>         { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, P3, P4, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType& param4, const MultiType&) { (*functionPointer)(param1, param2, param3, param4); return MultiType::Null; } };
-        template <bool isconst, class P1, class P2, class P3>                     struct FunctorCaller<void, void, isconst, P1, P2, P3, void, void>       { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, P3, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType& param3, const MultiType&, const MultiType&) { (*functionPointer)(param1, param2, param3); return MultiType::Null; } };
-        template <bool isconst, class P1, class P2>                               struct FunctorCaller<void, void, isconst, P1, P2, void, void, void>     { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, P2, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType& param2, const MultiType&, const MultiType&, const MultiType&) { (*functionPointer)(param1, param2); return MultiType::Null; } };
-        template <bool isconst, class P1>                                         struct FunctorCaller<void, void, isconst, P1, void, void, void, void>   { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, P1, void, void, void, void>::Type functionPointer, void*, const MultiType& param1, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { (*functionPointer)(param1); return MultiType::Null; } };
-        template <bool isconst>                                                   struct FunctorCaller<void, void, isconst, void, void, void, void, void> { static inline MultiType call(typename detail::FunctionPointer<void, void, isconst, void, void, void, void, void>::Type functionPointer, void*, const MultiType&, const MultiType&, const MultiType&, const MultiType&, const MultiType&) { (*functionPointer)(); return MultiType::Null; } };
+        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...); } };
+        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; } };
+        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...); } };
+        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; } };
 
         // Helper class, used to identify the header of a function-pointer (independent of its class)
-        template <class R, class P1, class P2, class P3, class P4, class P5>
+        template <class R, class... Params>
         struct FunctorHeaderIdentifier
         {};
 
@@ -447,25 +413,33 @@
         struct FunctorHasReturnvalue<void>
         { enum { result = false }; };
 
-        // Helper class to count the number of parameters
-        template <class P1, class P2, class P3, class P4, class P5>
-        struct FunctorParamCount
-        { enum { result = 5 }; };
-        template <class P1, class P2, class P3, class P4>
-        struct FunctorParamCount<P1, P2, P3, P4, void>
-        { enum { result = 4 }; };
-        template <class P1, class P2, class P3>
-        struct FunctorParamCount<P1, P2, P3, void, void>
-        { enum { result = 3 }; };
-        template <class P1, class P2>
-        struct FunctorParamCount<P1, P2, void, void, void>
-        { enum { result = 2 }; };
-        template <class P1>
-        struct FunctorParamCount<P1, void, void, void, void>
-        { enum { result = 1 }; };
-        template <>
-        struct FunctorParamCount<void, void, void, void, void>
-        { enum { result = 0 }; };
+        //Barebones implementation of (make_)index_sequence for C++11
+        template <std::size_t...> struct index_sequence {};
+
+        template <std::size_t N, std::size_t... Is>
+        struct make_index_sequence : make_index_sequence<N - 1, N - 1, Is...> {};
+
+        template <std::size_t... Is>
+        struct make_index_sequence<0u, Is...> : index_sequence<Is...> {};
+
+        //Helper structs to deduce the first N types of a parameter pack
+        template<class... Types> struct type_list {};
+
+        template <class T1, class... AllTypes>
+        struct make_type_list_helper
+        {
+            template <std::size_t N, class... Types>
+            struct make_type_list_impl : make_type_list_helper<AllTypes...>::template make_type_list_impl<N - 1, Types..., T1> {};
+
+            template <class... Types>
+            struct make_type_list_impl<1u, Types...> : type_list<Types..., T1> {};
+        };
+
+        template <std::size_t N, class... Types>
+        struct make_type_list : make_type_list_helper<Types...>::template make_type_list_impl<N> {};
+
+        template <class... Types>
+        struct make_type_list<0u, Types...> : type_list<> {};
     }
 
     /**
@@ -488,123 +462,116 @@
 
         All template arguments can be void.
     */
-    template <class R, class O, bool isconst, class P1, class P2, class P3, class P4, class P5>
-    class FunctorTemplate : public FunctorPointer<typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type, O>
+    template <class R, class O, bool isconst, class... Params>
+    class FunctorTemplate : public FunctorPointer<typename detail::FunctionPointer<R, O, isconst, Params...>::Type, O>
     {
+        static_assert(sizeof...(Params) <= 5, "Only up to 5 parameters are supported");
+
         public:
             /// Constructor: Initializes the base class.
-            FunctorTemplate(typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type functionPointer, O* object = nullptr) : FunctorPointer<typename detail::FunctionPointer<R, O, isconst, P1, P2, P3, P4, P5>::Type, O>(functionPointer, object) {}
+            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) {}
 
             // see FunctorMember::operator()()
-            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)
+            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
             {
-                return detail::FunctorCaller<R, O, isconst, P1, P2, P3, P4, P5>::call(this->functionPointer_, object, param1, param2, param3, param4, param5);
+                auto multis = std::make_tuple(param1, param2, param3, param4, param5);
+                return callHelper(object, multis, detail::make_index_sequence<sizeof...(Params)>{});
             }
 
             // see Functor::clone()
-            FunctorPtr clone()
+            virtual FunctorPtr clone() override
             {
                 return std::make_shared<FunctorTemplate>(*this);
             }
 
             // see Functor::evaluateArgument()
-            void evaluateArgument(unsigned int index, MultiType& argument) const
+            virtual void evaluateArgument(unsigned int index, MultiType& argument) const override
             {
-                switch (index)
+                static const std::array<std::function<bool(MultiType&)>, sizeof...(Params)> funcs = {&MultiType::convert<Params>...};
+                if (index < funcs.size())
                 {
-                    case 0: argument.convert<P1>(); break;
-                    case 1: argument.convert<P2>(); break;
-                    case 2: argument.convert<P3>(); break;
-                    case 3: argument.convert<P4>(); break;
-                    case 4: argument.convert<P5>(); break;
+                    funcs[index](argument);
                 }
             }
 
             // see Functor::getParamCount()
-            unsigned int getParamCount() const
+            virtual unsigned int getParamCount() const override
             {
-                return detail::FunctorParamCount<P1, P2, P3, P4, P5>::result;
+                return sizeof...(Params);
             }
 
             // see Functor::hasReturnvalue()
-            bool hasReturnvalue() const
+            virtual bool hasReturnvalue() const override
             {
                 return detail::FunctorHasReturnvalue<R>::result;
             }
 
             // see Functor::getTypenameParam()
-            std::string getTypenameParam(unsigned int index) const
+            virtual std::string getTypenameParam(unsigned int index) const override
             {
-                switch (index)
+                static const std::array<std::string, sizeof...(Params)> names = { typeToString<Params>()... };
+                if (index >= names.size())
                 {
-                    case 0:  return typeToString<P1>();
-                    case 1:  return typeToString<P2>();
-                    case 2:  return typeToString<P3>();
-                    case 3:  return typeToString<P4>();
-                    case 4:  return typeToString<P5>();
-                    default: return "";
+                    return "";
                 }
+                return names[index];
             }
 
             // see Functor::getTypenameReturnvalue()
-            std::string getTypenameReturnvalue() const
+            virtual std::string getTypenameReturnvalue() const override
             {
                 return typeToString<R>();
             }
 
             // see Functor::getHeaderIdentifier()
-            const std::type_info& getHeaderIdentifier() const
+            virtual const std::type_index getHeaderIdentifier() const override
             {
-                return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, P5>);
+                return typeid(detail::FunctorHeaderIdentifier<R, Params...>);
             }
 
             // see Functor::getHeaderIdentifier(unsigned int)
-            const std::type_info& getHeaderIdentifier(unsigned int params) const
+            virtual const std::type_index getHeaderIdentifier(unsigned int params) const override
             {
-                switch (params)
+                //+1 because e.g. for two parameters, we want typeids for zero, one, or two parameters
+                return getHeaderIdentifierHelper(params, detail::make_index_sequence<sizeof...(Params) + 1>{});
+            }
+
+    private:
+
+            /// Helper function that extracts index numbers of parameters from a tuple. Needed to call the function pointer with the correct amount of arguments.
+            template<typename Tup, std::size_t... index>
+            MultiType callHelper(O* object, Tup&& tup, detail::index_sequence<index...>)
+            {
+                return detail::FunctorCaller<R, O, isconst, Params...>::call(this->functionPointer_, object, std::get<index>(std::forward<Tup>(tup))...);
+            }
+
+            /// Helper function to extract all identifiers of the function pointer using a deduced index sequence
+            template<std::size_t... index>
+            const std::type_index& getHeaderIdentifierHelper(unsigned int params, detail::index_sequence<index...>) const
+            {
+                static const std::array<const std::type_index, sizeof...(index)> typeinfos = { getTypelistIdentifier(detail::make_type_list<index, Params...>{})... };
+                if (params >= typeinfos.size())
                 {
-                    case 0:  return typeid(detail::FunctorHeaderIdentifier<R, void, void, void, void, void>);
-                    case 1:  return typeid(detail::FunctorHeaderIdentifier<R, P1, void, void, void, void>);
-                    case 2:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, void, void, void>);
-                    case 3:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, void, void>);
-                    case 4:  return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, void>);
-                    default: return typeid(detail::FunctorHeaderIdentifier<R, P1, P2, P3, P4, P5>);
+                    return typeinfos.back();
                 }
+                return typeinfos[params];
             }
+
+            ///Helper function that deduces a parameter pack of types and returns the corresponding identifier
+            template<class... Types>
+            const std::type_index getTypelistIdentifier(detail::type_list<Types...>) const
+            {
+                return typeid(detail::FunctorHeaderIdentifier<R, Types...>);
+            }
     };
 
-    template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5), OO* object) { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4), OO* object)     { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, P3, P4, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3), OO* object)         { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, P3, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2), OO* object)             { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, void, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1), OO* object)                 { return std::make_shared<FunctorTemplate<R, O, false, P1, void, void, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(), OO* object)                   { return std::make_shared<FunctorTemplate<R, O, false, void, void, void, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const, OO* object) { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const, OO* object)     { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, P3, P4, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const, OO* object)         { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, P3, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const, OO* object)             { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, void, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const, OO* object)                 { return std::make_shared<FunctorTemplate<R, O, true, P1, void, void, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
-    template <class R, class O, class OO>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const, OO* object)                   { return std::make_shared<FunctorTemplate<R, O, true, void, void, void, void, void>>(functionPointer, object); }   ///< Creates a new FunctorMember with the given function-pointer and an assigned object
+    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
+    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
 
-    template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5)) { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, P3, P4, P5>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4))     { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, P3, P4, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3))         { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, P3, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2))             { return std::make_shared<FunctorTemplate<R, O, false, P1, P2, void, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1))                 { return std::make_shared<FunctorTemplate<R, O, false, P1, void, void, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)())                   { return std::make_shared<FunctorTemplate<R, O, false, void, void, void, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1, class P2, class P3, class P4, class P5> inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4, P5) const) { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, P3, P4, P5>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1, class P2, class P3, class P4>           inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3, P4) const)     { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, P3, P4, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1, class P2, class P3>                     inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2, P3) const)         { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, P3, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1, class P2>                               inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1, P2) const)             { return std::make_shared<FunctorTemplate<R, O, true, P1, P2, void, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O, class P1>                                         inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)(P1) const)                 { return std::make_shared<FunctorTemplate<R, O, true, P1, void, void, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
-    template <class R, class O>                                                   inline FunctorMemberPtr<O> createFunctor(R (O::*functionPointer)() const)                   { return std::make_shared<FunctorTemplate<R, O, true, void, void, void, void, void>>(functionPointer); }   ///< Creates a new FunctorMember with the given function-pointer
+    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
+    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
 
-    template <class R, class P1, class P2, class P3, class P4, class P5> inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4, P5)) { return std::make_shared<FunctorTemplate<R, void, false, P1, P2, P3, P4, P5>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
-    template <class R, class P1, class P2, class P3, class P4>           inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3, P4))     { return std::make_shared<FunctorTemplate<R, void, false, P1, P2, P3, P4, void>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
-    template <class R, class P1, class P2, class P3>                     inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2, P3))         { return std::make_shared<FunctorTemplate<R, void, false, P1, P2, P3, void, void>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
-    template <class R, class P1, class P2>                               inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1, P2))             { return std::make_shared<FunctorTemplate<R, void, false, P1, P2, void, void, void>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
-    template <class R, class P1>                                         inline FunctorStaticPtr createFunctor(R (*functionPointer)(P1))                 { return std::make_shared<FunctorTemplate<R, void, false, P1, void, void, void, void>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
-    template <class R>                                                   inline FunctorStaticPtr createFunctor(R (*functionPointer)())                   { return std::make_shared<FunctorTemplate<R, void, false, void, void, void, void, void>>(functionPointer); }   ///< Creates a new Functor with the given function-pointer
+    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
 }
 
 #endif /* _Functor_H__ */




More information about the Orxonox-commit mailing list