gpt4 book ai didi

c++ - 如何转换C++11中忽略参数的函数?

转载 作者:行者123 更新时间:2023-12-02 19:59:49 25 4
gpt4 key购买 nike

我正在寻找更优雅的代码来忽略不必要的参数。有点反转 std::bind。

void doSomething(function<A(B)> callback); // Given function

// Instead of
void myDoSomething(function<A()> callback0) {
doSomething([&](B b) {
return callback0();
});
}

// I want
void myDoSomething(function<A()> callback0) {
doSomething(add_ignored_arg<B>(callback0));
}

最佳答案

选项#1

C++11基本解决方案,将忽略的参数注入(inject)到第一个位置( DEMO 1 ):

template <typename Arg, typename R, typename... Args>
std::function<R(Arg, Args...)> add_ignored_arg(std::function<R(Args...)> f)
{
return [f] (Arg&& /*arg*/, Args&&... args) { return f(std::forward<Args>(args)...); };
}

注意: std::forward<Args>(args)Args&& 以来工作正常(尽管 std::function 不是转发引用)将按值传递的参数强制转换为右值引用,而左值引用则根据规则折叠:& && -> & .

选项#2

使用通用 lambda 的 C++14 基本解决方案,将忽略的参数注入(inject)第一个位置 ( DEMO 2 ):

template <typename Arg, typename R, typename... Args>
std::function<R(Arg, Args...)> add_ignored_arg(std::function<R(Args...)> f)
{
return [f] (auto&& /*arg*/, auto&&... args) { return f(std::forward<decltype(args)>(args)...); };
}

选项#3

C++11 高级解决方案,可将忽略的参数注入(inject)到任何位置,并具有接受原始函数指针std::function 的附加重载包装器(DEMO 3):

template <std::size_t N, typename Arg, typename R, typename... Args, std::size_t... Before, std::size_t... After, typename Tuple = std::tuple<Args...>>
auto inject_param(index_sequence<Before...>, index_sequence<After...>)
-> std::function<R(typename std::tuple_element<Before, Tuple>::type..., Arg, typename std::tuple_element<N + After, Tuple>::type...)>;

template <std::size_t N, typename Arg, typename R, typename... Args, std::size_t... Before, std::size_t... After, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f, index_sequence<Before...>, index_sequence<After...>)
-> decltype(inject_param<N, Arg, R, Args...>(index_sequence<Before...>{}, index_sequence<After...>{}))
{
return [f] (typename std::tuple_element<Before, Tuple>::type&&... before
, Arg&& /*arg*/
, typename std::tuple_element<N + After, Tuple>::type&&... after)
{
return f(std::forward<typename std::tuple_element<Before, Tuple>::type>(before)...,
std::forward<typename std::tuple_element<N + After, Tuple>::type>(after)...);
};
}

template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f)
-> decltype(inject_param<N, Arg, R, Args...>(make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{}))
{
return add_ignored_arg<N, Arg>(f, make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{});
}

template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(R(*f)(Args...))
-> decltype(inject_param<N, Arg, R, Args...>(make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{}))
{
return add_ignored_arg<N, Arg>(std::function<R(Args...)>(f), make_index_sequence<N>{}, make_index_sequence<sizeof...(Args) - N>{});
}

注意:实现index_sequence是在演示中。转发工作如选项 #1 中所述。

选项#4

C++14 高级解决方案,使用通用 lambda 和返回类型推导 ( DEMO 4 ) 将被忽略的参数注入(inject)到任何位置:

template <std::size_t N, typename Arg, typename R, typename... Args, std::size_t... Before, std::size_t... After, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f, std::index_sequence<Before...>, std::index_sequence<After...>)
-> std::function<R(typename std::tuple_element<Before, Tuple>::type..., Arg, typename std::tuple_element<N + After, Tuple>::type...)>
{
return [f] (auto&&... args)
{
auto t = std::forward_as_tuple(std::forward<decltype(args)>(args)...);
return f(static_cast<typename std::tuple_element<Before, decltype(t)>::type>(std::get<Before>(t))...,
static_cast<typename std::tuple_element<N + After + 1, decltype(t)>::type>(std::get<N + After + 1>(t))...);
};
}

template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(std::function<R(Args...)> f)
{
return add_ignored_arg<N, Arg>(f, std::make_index_sequence<N>{}, std::make_index_sequence<sizeof...(Args) - N>{});
}

template <std::size_t N, typename Arg, typename R, typename... Args, typename Tuple = std::tuple<Args...>>
auto add_ignored_arg(R(*f)(Args...))
{
return add_ignored_arg<N, Arg>(std::function<R(Args...)>(f), std::make_index_sequence<N>{}, std::make_index_sequence<sizeof...(Args) - N>{});
}
<小时/>

测试

struct B {};

void foo(int i, char c, double d)
{
std::cout << i << " " << c << " " << d << std::endl;
}

void doSomething(std::function<void(int, char, B, double)> callback)
{
callback(123, 'A', B{}, 3.14f);
}

void myDoSomething(std::function<void(int, char, double)> callback)
{
doSomething(add_ignored_arg<2, B>(callback));
}

int main()
{
myDoSomething(&foo);
}

输出:

123 A 3.14

Complete C++11 demo

Complete C++14 demo

关于c++ - 如何转换C++11中忽略参数的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26174125/

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