gpt4 book ai didi

c++ - 传递可变参数 std::function

转载 作者:行者123 更新时间:2023-11-30 00:43:42 33 4
gpt4 key购买 nike

我有一个接受回调的函数。它应该与函数 ptrs、lambdas(无状态和有状态)等一起使用。我可以执行以下操作:

template<typename t_func>
void add_command(const std::string& name, t_func func)

问题是我需要使用 func 的参数类型。所以我这样做了:

template<typename... t_args>
void add_command(const std::string& name, const std::function<void(t_args...)>& args)

这会产生以下错误:没有匹配的调用函数...

注意:模板参数推导/替换失败

有什么方法可以在传递泛型函数类型的同时仍然可以访问它的参数吗?我知道 std::result_of,是否有类似的 std::arguments_of

最佳答案

std::function 是类型删除模板。类型推导与类型删除相反(几乎相反)。

类型推导类型删除模板是代码味道。而且它很少奏效。

有一个推导指南,所以你可以这样做:

template<typename... t_args>
void add_command(const std::string& name, const std::function<void(t_args...)>& args)
void add_command(const std::string& name, t_func const& func) {
std::function f = func;
add_command(name, f);
}

它不完美,但完美的解决方案是不可能的。

演绎指南look like :

template<class R, class... ArgTypes>
function(R(*)(ArgTypes...)) -> function<R(ArgTypes...)>;
template<class F>
function(F) -> function</*see below*/>;

它通过检查 &F::operator() 来提取 function 的签名。这可能因重载或模板而失败。当然,这不适用于重载的函数名称。

您可以在 中复制它具有功能特征类:

template<class X>
struct function_traits:function_traits<decltype(&X::operator())> {};
#define MEM_FUN_HELPER2(...) \
template<class R, class T, class...Args> \
struct function_traits<R(T::*)(Args...) __VA_ARGS__>:function_traits<R(Args...)>{}; \
template<class R, class T, class...Args> \
struct function_traits<R(T::*)(Args..., ...) __VA_ARGS__>:function_traits<R(Args..., ...)>{}; \
template<class R, class T, class...Args> \
struct function_traits<R(T::*)(Args...) __VA_ARGS__ noexcept>:function_traits<R(Args...) noexcept>{}; \
template<class R, class T, class...Args> \
struct function_traits<R(T::*)(Args..., ...) __VA_ARGS__ noexcept>:function_traits<R(Args..., ...) noexcept>{}
#define MEM_FUN_HELPER1(...) \
MEM_FUN_HELPER2(__VA_ARGS__); \
MEM_FUN_HELPER2(__VA_ARGS__ &); \
MEM_FUN_HELPER2(__VA_ARGS__ &&)
#define MEM_FUN_HELPER0(...) \
MEM_FUN_HELPER1(__VA_ARGS__); \
MEM_FUN_HELPER1(const __VA_ARGS__)
#define MEM_FUN_HELPER() \
MEM_FUN_HELPER0(); \
MEM_FUN_HELPER0(volatile)

MEM_FUN_HELPER();

template<class R, class...Args>
struct function_traits<R(*)(Args...)>:function_traits<R(Args...)>{};
template<class R, class...Args>
struct function_traits<R(*)(Args..., ...)>:function_traits<R(Args..., ...)>{};
template<class R, class...Args>
struct function_traits<R(*)(Args...) noexcept>:function_traits<R(Args...) noexcept>{};
template<class R, class...Args>
struct function_traits<R(*)(Args..., ...) noexcept>:function_traits<R(Args..., ...) noexcept>{};
template<class R, class...Args>
struct function_traits<R(Args...) noexcept> : function_traits<R(Args...)> {
enum {is_noexcept=true};
};
template<class R, class...Args>
struct function_traits<R(Args..., ...) noexcept> : function_traits<R(Args..., ...)> {
enum {is_noexcept=true};
};
template<class R, class...Args>
struct function_traits<R(Args...)> {
template<template<class...>class Z>
using transcribe=Z<R(Args...)>;
using std_function = transcribe<std::function>;
using result_type = R;
using arg_tuple = std::tuple<Args...>;
enum{is_noexcept=false};
};
template<class R, class...Args>
struct function_traits<R(Args..., ...)> {
template<template<class...>class Z>
using transcribe=Z<R(Args..., ...)>;
using std_function = transcribe<std::function>;
using result_type = R;
// doesn't really work, but what ya gonna do:
using arg_tuple = std::tuple<Args...>;
enum{is_noexcept=false};
};

这太疯狂了; MEM_FUN_HELPER(); 扩展为 48 个模板特化。 3 个 ref 限定符(&&& 什么都没有),然后是 4 个其他的东西(constvolatilenoexcept... 必须“手动”处理的 C 风格可变参数)。

无论如何,一旦有了它,您就可以:

template<typename... t_args>
void add_command(const std::string& name, const std::function<void(t_args...)>& args)
template<class t_func>
void add_command(const std::string& name, t_func const& func) {
typename function_traits<t_func>::std_function f = func;
add_command(name, f);
}

.这(粗略地和不完美地)与 相同。演绎指南。

Live example .

关于c++ - 传递可变参数 std::function,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52742133/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com