有没有办法从函子中取出第一个参数的类型?

Is there a way to pull out the type of the 1st parameter from a functor?

本文关键字:第一个 参数 类型 有没有      更新时间:2023-10-16

给定任何函子,我想提取它接受的第一个参数的类型。可以假定函子只接受一个参数。我可以用函数做到这一点,但我正在寻找一个函子的解决方案。

#include <iostream>
#include <utility>
template <typename T>
struct test;
template <typename R, typename P>
struct test<R(*)(P)>
{
    typedef R R_t;
    typedef P P_t;
};
void fn(int value)
{
    std::cout << "function called " << value << std::endl;
}
int main()
{
    using namespace std;
    cout << typeid(test<decltype(&fn)>::R_t).name() << endl;
    cout << typeid(test<decltype(&fn)>::P_t).name() << endl;
}

解决方案

给定

:

template <typename T>
struct member_function_traits;
template <typename C, typename R, typename... Args>
struct member_function_traits<R(C::*)(Args...)> {
    using return_type = R;
    template <std::size_t i>
    struct param {
        typedef typename std::tuple_element<i, std::tuple<Args...>>::type type;
    };
};

你可以:

template<typename Functor>
struct functor_traits {
    using return_type = typename member_function_traits<decltype(&Functor::operator())>::return_type;
    template<std::size_t i>
    using param = typename member_function_traits<decltype(&Functor::operator())>::template param<i>;
};

例子

例如,有:

struct functor {
    void operator()(int) {}
};

以下程序:

std::cout << std::is_same<functor_traits<functor>::return_type, void>::value << std::endl;
std::cout << std::is_same<functor_traits<functor>::param<0>::type, int>::value << std::endl;

打印:

1
1

现场演示

如果您只想要第一个参数类型,然后你可以使用局部专门化,使用可变模板来分离第一个参数和其余参数。

我的方法和Jeffery一样,但是不使用tuple。

template<typename T>
struct member_fn_traits;
template<typename C, typename R, typename First, typename... Rest>
struct member_fn_traits<R (C::*)(First, Rest...)>
{
    using first_type = First;
};
template<typename Functor>
struct fn_traits
{
     using first_type = typename member_fn_traits<decltype(&Functor::operator())>::first_type;
};
struct functor 
{
    void operator()(int*, int) {}
};

auto main()
{
    auto first_var = fn_traits<functor>::first_type{};
}