I have the following, it accepts a function pointer type, and returns the typeid of each argument in a vector.
template <typename Ret, typename... Types>
auto ArgTypes(Ret(*pFn)(Types...))
{
std::vector<std::type_index> vec;
vec.insert(vec.end(), {typeid(Types)...});
return vec;
}
I invoke it like this:
typedef int (*tExampleFn) (int a,bool b,char* c,long long d);
tExampleFn fakePtr = (tExampleFn)0;
auto argTypes = ArgTypes(&fakePtr);
As you can see, I have to make this fake function pointer for the template to work. I would instead like it to work like this:
template <typename Ret, typename... Types> // guide Ret and Types into shape Ret(*pFn)(Types...) somehow
auto ArgTypes()
{
std::vector<std::type_index> vec;
vec.insert(vec.end(), {typeid(Types)...});
return vec;
}
typedef int (*tExampleFn) (int a,bool b,char* c,long long d);
auto argTypes = ArgTypes<tExampleFn>();
I cannot get the template to work this way. The first template arg Ret gets assinged the full type of the typedef tExampleFn. How can I guide the template to use the shape Ret(*pFn)(Types...), but without having to pass an intermediate function pointer.
CodePudding user response:
As mentioned by NathanOliver you can call the first version via ArgTypes(tExampleFn{})
.
To avoid creating an instance of the function pointer type altogether you can use partial template specialization. This doesn't work for function templates though.
#include <vector>
#include <typeindex>
#include <tuple>
template <typename Ret, typename... Types>
auto ArgTypes(Ret(*pFn)(Types...))
{
std::vector<std::type_index> vec;
vec.insert(vec.end(), {typeid(Types)...});
return vec;
}
template <typename T>
struct arg_types;
template <typename Ret,typename ... Types>
struct arg_types<Ret(*)(Types...)> {
auto operator()() {
std::vector<std::type_index> vec;
vec.insert(vec.end(), {typeid(Types)...});
return vec;
}
};
int main()
{
typedef int (*tExampleFn) (int a,bool b,char* c,long long d);
ArgTypes(tExampleFn{});
arg_types<tExampleFn>{}();
}
CodePudding user response:
Thanks everyone, I've combined the answers and comments with some external help into the following:
#include <iostream>
#include <typeinfo>
#include <typeindex>
#include <span>
typedef int (*tExampleFn) (int a,bool b,char* c,long long d);
template<typename T>
struct arg_types {};
template<typename R, typename... A>
struct arg_types<R(*)(A...)> {
inline static const std::type_index value[] = {typeid(A)...};
};
template<typename T>
static constexpr std::span<const std::type_index> arg_types_v = arg_types<T>::value;
int main()
{
auto vec = arg_types_v<tExampleFn>;
for (const auto& t : vec)
{
std::cout << t.hash_code() << std::endl;
}
}