gpt4 book ai didi

c++ - 如何将 std::function 包装器转换为可变参数函数?

转载 作者:太空狗 更新时间:2023-10-29 20:21:00 30 4
gpt4 key购买 nike

我有一个非常好的包装器,但我希望它能接受任意数量的 T、S、R、Q、...

template<typename U, typename T, typename S>
boost::variant<U, std::string> RunSafeFn2(const std::function<U(const T&,const S&)>& f, const std::string& errMsg, const T& a1, const S& a2)
{
try
{
return f(a1,a2);
}
catch (...)
{
return errMsg;
}
}

我尝试了下面的内容并一直在谷歌搜索,但是错误消息是神秘的 - 我正在尝试做的事情甚至可能吗?

template<typename U, class ... Ts>
boost::variant<U, std::string> RunSafeFnN(const std::function<U(Ts)>& f, const std::string& errMsg, Ts ... ts)
{
try
{
return bind(f, ts...);
}
catch (...)
{
return errMsg;
}
}

最佳答案

你可以做你想做的,正如这个简单的程序所示:

template <class ... Ts>
void foo(std::function<void(Ts...)> f, Ts && ... ts) {
f(std::forward<Ts>(ts)...);
}

int main()
{
std::function<void(int)> f = [] (int i) { std::cerr << "hello " << i; };
foo(f, 5);
return 0;
}

问题是,一旦 RunSafeFn2 是一个模板,您也可以模板化仿函数本身。当您已经是模板时,键入删除可调用对象几乎没有什么好处。所以在实践中,这样做更有意义:

template <class F, class ... Ts>
void foo(F f, Ts && ... ts) {
f(std::forward<Ts>(ts)...);
}

这仍然允许上面的用法,但也允许做:

foo([] (int i) { std::cerr << "hello " << i; }, 5);

这也会更有效,因为您完全避免创建 std::function 对象。要处理返回类型,由于您仅限于 C++11,您可以这样做:

template <class F, class ... Ts>
auto foo(F f, Ts && ... ts) -> boost::variant<decltype(f(std::forward<Ts>(ts)...)), std::string> {
try {
return f(std::forward<Ts>(ts)...);
}
...
}

编辑:让我添加一个最后的想法:在 C++11 及更高版本中,可调用对象很容易创建,一个更简单的替代方法实际上是采用可调用对象并且没有参数:

template <class F>
auto foo(F f) -> boost::variant<decltype(f()), std::string> {
try {
return f();
}
...
}

那是因为围绕您需要的参数很容易捕捉到。例如,如果我以这种方式编写了我的原始示例,我可以通过执行以下操作来使用它:

int i = 5;
foo([&] () { std::cerr << "hello " << i; });

这有利有弊,尤其是在处理仅移动类型时,但如果您想最大程度地减少维护负担并且您的用例很简单,这是一个合理的选择。

关于c++ - 如何将 std::function 包装器转换为可变参数函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46594720/

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