我有以下代码,它接受一个函数指针类型,并返回vector中每个参数的类型id。
template <typename Ret, typename... Types>
auto ArgTypes(Ret(*pFn)(Types...))
{
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);
tExampleFn fakePtr = (tExampleFn)0;
auto argTypes = ArgTypes(&fakePtr);
如你所见,我必须使这个伪函数指针的模板工作。相反,我希望它像这样工作:
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>();
我无法让模板以这种方式工作。第一个模板参数Ret被赋值为typedef tExampleFn的完整类型。我如何引导模板使用形状Ret(*pFn)(类型…),但没有必须传递中间函数指针。
正如NathanOliver所提到的,你可以通过ArgTypes(tExampleFn{})
调用第一个版本。
为了避免创建函数指针类型的实例,可以使用部分模板特化。但这对函数模板不起作用。
#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>{}();
}
谢谢大家,我把大家的回答和评论与一些外部帮助结合在一起,形成了以下内容:
#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;
}
}