gpt4 book ai didi

C++:获取 std::bind 产生的参数

转载 作者:太空狗 更新时间:2023-10-29 21:27:17 26 4
gpt4 key购买 nike

首先,介绍一些背景知识:在我的工作中,我们绑定(bind)了稍后调用的回调,这使得尝试通过日志跟踪控制流变得非常困难。为帮助实现这一点,我们使用“日志上下文”,它让您可以在请求通过系统时跟踪它。您可以使用静态函数复制出当前上下文 log_context::get_current并用静态函数恢复它 log_context::set_current .这导致每次我们将回调发布到工作队列时都会导致大量重复代码。

我想创建一个函数来替代 std::bind这将保存当前的 log_context并在调用时恢复它。但是,我在编写它时遇到了一些问题。

现在,函数看起来像这样:

template <typename TResult,
typename... TFuncArgs,
typename Func,
typename... TProvidedArgs
>
std::function<TResult (TFuncArgs...)>
bind_with_context(const std::function<TResult (TFuncArgs...)>& throwaway,
Func func,
TProvidedArgs&&... args
)
{
log_context cxt = log_context::get_current();
auto bound = std::bind(func, std::forward<TProvidedArgs>(args)...);
auto lambda = [cxt, bound] (TFuncArgs... args) -> TResult
{
log_context::set_current(cxt);
return bound(args...);
};
return lambda;
}

它有效,但问题是用法要求您无缘无故地传递函数类型(除此之外,我就是这样找出要用于 TFuncArgs 的内容):

bind_with_context(func_type(), &some_class::some_func, ptr, _1, "Bob", _2);

所以,不完全是替代品。似乎有人应该在编译时知道这些信息,我只是想不通如何。 快到了如何消除传入函数类型的需要?


我最初的想法是将绑定(bind)从将其转换为函数中分离出来,如下所示:

template <typename Func>
struct context_binder
{
public:
context_binder(const Func& func) :
func(func)
{ }

// Use the casting operator to figure out what we're looking for:
template <typename TReturn, typename... TFuncArgs>
operator std::function<TReturn (TFuncArgs...)>() const
{
log_context cxt = log_context::get_current();
auto lambda = [func, cxt] (TFuncArgs... args) -> TReturn
{
log_context::set_current(cxt);
return func(std::forward<TFuncArgs>(args)...);
};
return lambda;
}

private:
Func func;
};

template <typename F, typename... TArgs>
auto bind_with_context(F f, TArgs&&... args)
-> context_binder<decltype(std::bind(f, std::forward<TArgs>(args)...))>
{
return std::bind(f, std::forward<TArgs>(args)...);
}

问题是转换 (operator std::function<TReturn (TFuncArgs...)>() const) 将永远不会被调用(给定 int foo(int x, int y, int z)):

std::function<int (int)> f = bind_with_context(&foo, 4, 5, _1);

原因是function s 的构造函数试图获取 operator ()来自 context_binder (即使它没有)。

In file included from scratch.cpp:1:0:
/usr/local/include/gcc-4.6.2/functional: In static member function ‘static _Res std::_Function_handler<_Res(_ArgTypes ...), _Functor>::_M_invoke(const std::_Any_data&, _ArgTypes ...) [with _Res = int, _Functor = context_binder<std::_Bind<int (*(int, int, std::_Placeholder<1>))(int, int, int)> >, _ArgTypes = {int}]’:
/usr/local/include/gcc-4.6.2/functional:2148:6: instantiated from ‘std::function<_Res(_ArgTypes ...)>::function(_Functor, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type) [with _Functor = context_binder<std::_Bind<int (*(int, int, std::_Placeholder<1>))(int, int, int)> >, _Res = int, _ArgTypes = {int}, typename std::enable_if<(! std::is_integral<_Functor>::value), std::function<_Res(_ArgTypes ...)>::_Useless>::type = std::function<int(int)>::_Useless]’
scratch.cpp:53:85: instantiated from here
/usr/local/include/gcc-4.6.2/functional:1764:40: error: no match for call to ‘(context_binder<std::_Bind<int (*(int, int, std::_Placeholder<1>))(int, int, int)> >) (int)’

所以我对这个几乎解决方案的问题是:有没有办法得到 g++更喜欢我的弃用运算符而不是尝试使用 function的构造函数?

最佳答案

解决方案是使用 operator () 将绑定(bind)与转换为 std::function 分开:

template <typename Func>
struct context_binder
{
private:
Func func;
log_context cxt;

public:
context_binder(const Func& func) :
func(func),
cxt(log_context::get_current())
{ }

template <typename... TArgs>
auto operator ()(TArgs&&... args) const
-> decltype(func(std::forward<TArgs>(args)...))
{
log_context::set_current(cxt);
return func(std::forward<TArgs>(args)...);
}
};

template <typename F, typename... TArgs>
auto bind_with_context(F f, TArgs&&... args)
-> context_binder<decltype(std::bind(f, std::forward<TArgs>(args)...))>
{
return std::bind(f, std::forward<TArgs>(args)...);
}

当有人试图将 context_binder 分配给 std::function(其非整数尝试的构造函数获取 operator())。

关于C++:获取 std::bind 产生的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9382411/

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