Im trying to get the argument types from a function pointer
This should be the working end product
std::function<void(TestAppObject*, MemberFuncArgs<decltype(&TestAppObject::TestMethod)>::InputArgs)> func = &TestAppObject::TestMethod;
Current MemberFuncArgs class
template<typename T>
struct MemberFuncArgs;
template<typename RT, typename Owner, typename ...Args>
struct MemberFuncArgs<RT(Owner::*)(Args...)>
{
static const size_t ArgCount = sizeof...(Args);
typedef RT ReturnType;
typedef Args InputArgs;
};
Compiler throws the error 'Args': parameter pack must be expanded in this context
.
I just need a way to extract the Args...
type from the function pointer, its probably just a syntax issue that im too dumb to see...
CodePudding user response:
The compiler say the you can't define a single type InputArgs
typedef Args InputArgs;
given that Args
is a variadic list.
Maybe you can define a type base on a tuple
using InArgsTuple = std::tuple<Args...>;
so you can extract the single types in Args...
using std::tuple_element
So, with a little template meta-programming, you should be able to write something as
using TplT = MemberFuncArgs<decltype(&TestAppObject::TestMethod)>::InArgsTuple;
std::function<void(TestAppObject*, typename std::tuple_element<Is, TplT>::type ...)>
func = &TestAppObject::TestMethod;
assuming that Is...
is a variadic sequence of template integer values from zero to sizeof...(Args)-1
.
The following is a full compiling C 20 example
#include <tuple>
#include <functional>
struct TestAppObject
{
int TestMethod (char, short, int, long, long long)
{ return 0; }
};
template <typename T>
struct MemberFuncArgs;
template <typename RT, typename Owner, typename ... Args>
struct MemberFuncArgs<RT(Owner::*)(Args...)>
{
static constexpr std::size_t ArgCount = sizeof...(Args);
using ReturnType = RT;
using InArgsTuple = std::tuple<Args...>;
};
int main()
{
using MFA = MemberFuncArgs<decltype(&TestAppObject::TestMethod)>;
using FunT = decltype([]<std::size_t ... Is>(std::index_sequence<Is...>)
-> std::function<void(TestAppObject*,
typename std::tuple_element<Is, MFA::InArgsTuple>::type ...)>
{ return {}; }
(std::make_index_sequence<MFA::ArgCount>{}));
FunT func = &TestAppObject::TestMethod;
}
If you can't use C 20 (so no template lambda and no lambda in not evaluated context) you can substitute the lambda with a traditional template function, only declared (because is used only inside decltype()
.
The following is a full compiling C 14/C 17 example. #include #include
struct TestAppObject
{
int TestMethod (char, short, int, long, long long)
{ return 0; }
};
template <typename T>
struct MemberFuncArgs;
template <typename RT, typename Owner, typename ... Args>
struct MemberFuncArgs<RT(Owner::*)(Args...)>
{
static constexpr std::size_t ArgCount = sizeof...(Args);
using ReturnType = RT;
using InArgsTuple = std::tuple<Args...>;
};
template <typename MFA, std::size_t ... Is>
std::function<void(TestAppObject*,
typename std::tuple_element<Is, typename MFA::InArgsTuple>::type ...)>
extra_function (std::index_sequence<Is...>);
int main()
{
using MFA = MemberFuncArgs<decltype(&TestAppObject::TestMethod)>;
using FunT = decltype(extra_function<MFA>
(std::make_index_sequence<MFA::ArgCount>{}));
FunT func = &TestAppObject::TestMethod;
}