Home > Net >  Guide C Function Template Type
Guide C Function Template Type

Time:06-10

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;
    }
}
  • Related