在现代 C++ 中有没有什么好的方法来获取 arg 类型列表形式的函数指针?
Is there any good way to obtain the arg type list form function pointer in modern c++?
假设我有函数指针R(*fp)(...A)
。有什么方法可以获取类型 R
和类型列表 A...
吗? std::invoke_result_t
好像不行。我找不到参数列表的任何内容。
#include <iostream>
#include <cstdlib>
#include <type_traits>
typedef int(*fp_t)(int, float);
std::invoke_result_t<fp_t> x = 10;
int main()
{
std::cout << "Hello, Wandbox!" << std::endl;
std::cout << x << std::endl;
}
用 c++17 编译给出错误:
/opt/wandbox/gcc-head/include/c++/10.0.0/type_traits: In substitution of 'template<class _Fn, class ... _Args> using invoke_result_t = typename std::invoke_result::type [with _Fn = int (*)(int, float); _Args = {}]':
prog.cc:6:26: required from here
/opt/wandbox/gcc-head/include/c++/10.0.0/type_traits:2917:11: error: no type named 'type' in 'struct std::invoke_result<int (*)(int, float)>'
2917 | using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
变化:
std::invoke_result_t<fp_t>
至:
std::invoke_result_t<fp_t, int, float> x = 10;
因为您还需要方法参数的类型,正如@Fureeish 在 ref 中评论和确认的那样。
使用 Clang 编译它(如 ) and see the Live demo.
中所建议
不确定您到底想要什么,但在我看来您正在寻找 std::function
演绎指南(在 C++17 中引入)。
有
using fnT = decltype(std::function{std::declval<fp_t>()});
你获得一个std::function<int(int, float)>
.
添加以下自定义类型特征
template <typename>
struct toTuple;
template <typename R, typename ... As>
struct toTuple<std::function<R(As...)>>
{
using retType = R;
using argTypes = std::tuple<As...>;
};
你可以获得return类型
using rT = typename toTuple<fnT>::retType;
或带有参数
的std::tuple
using asT = typename toTuple<fnT>::argTypes;
使用std::tuple_element_t
你可以提取单个参数类型。
下面是一个完整的编译示例
#include <tuple>
#include <iostream>
#include <functional>
#include <type_traits>
typedef int(*fp_t)(int, float);
template <typename>
struct toTuple;
template <typename R, typename ... As>
struct toTuple<std::function<R(As...)>>
{
using retType = R;
using argTypes = std::tuple<As...>;
};
int main()
{
using fnT = decltype(std::function{std::declval<fp_t>()});
using rT = typename toTuple<fnT>::retType;
using asT = typename toTuple<fnT>::argTypes;
static_assert( std::is_same_v<fnT, std::function<int(int, float)>> );
static_assert( std::is_same_v<rT, int> );
static_assert( std::is_same_v<std::tuple_element_t<0u, asT>, int> );
static_assert( std::is_same_v<std::tuple_element_t<1u, asT>, float> );
}
使用模板元函数推导它们:
#include <tuple>
typedef int(*fp_t)(int, float);
template <class T>
struct function_signature{};
template <class Return, class... Args>
struct function_signature<Return(*)(Args...)> {
using return_type = Return;
using args = std::tuple<Args...>;
};
int main()
{
using ret = function_signature<fp_t>::return_type;
using args = function_signature<fp_t>::args;
}
假设我有函数指针R(*fp)(...A)
。有什么方法可以获取类型 R
和类型列表 A...
吗? std::invoke_result_t
好像不行。我找不到参数列表的任何内容。
#include <iostream>
#include <cstdlib>
#include <type_traits>
typedef int(*fp_t)(int, float);
std::invoke_result_t<fp_t> x = 10;
int main()
{
std::cout << "Hello, Wandbox!" << std::endl;
std::cout << x << std::endl;
}
用 c++17 编译给出错误:
/opt/wandbox/gcc-head/include/c++/10.0.0/type_traits: In substitution of 'template<class _Fn, class ... _Args> using invoke_result_t = typename std::invoke_result::type [with _Fn = int (*)(int, float); _Args = {}]':
prog.cc:6:26: required from here
/opt/wandbox/gcc-head/include/c++/10.0.0/type_traits:2917:11: error: no type named 'type' in 'struct std::invoke_result<int (*)(int, float)>'
2917 | using invoke_result_t = typename invoke_result<_Fn, _Args...>::type;
变化:
std::invoke_result_t<fp_t>
至:
std::invoke_result_t<fp_t, int, float> x = 10;
因为您还需要方法参数的类型,正如@Fureeish 在 ref 中评论和确认的那样。
使用 Clang 编译它(如
不确定您到底想要什么,但在我看来您正在寻找 std::function
演绎指南(在 C++17 中引入)。
有
using fnT = decltype(std::function{std::declval<fp_t>()});
你获得一个std::function<int(int, float)>
.
添加以下自定义类型特征
template <typename>
struct toTuple;
template <typename R, typename ... As>
struct toTuple<std::function<R(As...)>>
{
using retType = R;
using argTypes = std::tuple<As...>;
};
你可以获得return类型
using rT = typename toTuple<fnT>::retType;
或带有参数
的std::tuple
using asT = typename toTuple<fnT>::argTypes;
使用std::tuple_element_t
你可以提取单个参数类型。
下面是一个完整的编译示例
#include <tuple>
#include <iostream>
#include <functional>
#include <type_traits>
typedef int(*fp_t)(int, float);
template <typename>
struct toTuple;
template <typename R, typename ... As>
struct toTuple<std::function<R(As...)>>
{
using retType = R;
using argTypes = std::tuple<As...>;
};
int main()
{
using fnT = decltype(std::function{std::declval<fp_t>()});
using rT = typename toTuple<fnT>::retType;
using asT = typename toTuple<fnT>::argTypes;
static_assert( std::is_same_v<fnT, std::function<int(int, float)>> );
static_assert( std::is_same_v<rT, int> );
static_assert( std::is_same_v<std::tuple_element_t<0u, asT>, int> );
static_assert( std::is_same_v<std::tuple_element_t<1u, asT>, float> );
}
使用模板元函数推导它们:
#include <tuple>
typedef int(*fp_t)(int, float);
template <class T>
struct function_signature{};
template <class Return, class... Args>
struct function_signature<Return(*)(Args...)> {
using return_type = Return;
using args = std::tuple<Args...>;
};
int main()
{
using ret = function_signature<fp_t>::return_type;
using args = function_signature<fp_t>::args;
}