gpt4 book ai didi

c++ - 递归调用重载的c++函数

转载 作者:行者123 更新时间:2023-11-30 02:41:11 24 4
gpt4 key购买 nike

我有一些自定义类型将用作函数的不同参数:

struct A {};
struct B {};
struct C {};
struct D {};
struct E {};

还有一些函数返回仿函数包装器:

template <typename H>
auto foo (H h,
enable_if_t<is_same<typename result_of<H(A)>::type, bool>::value>* = 0)
{
return [h] (B x) { return h (A {}); };
}

这个东西将 H (A) 仿函数转换为 G (B) 仿函数,转换输入参数 B->A(为简单起见,此处未实现)并使用 A 调用 H。

我有类似的转换器 C->B、D->C、E->D:

template <typename H>
auto foo (H h,
enable_if_t<is_same<typename result_of<H(B)>::type, bool>::value>* = 0)
{
return [h] (C x) { return h (B {}); };
}

template <typename H>
auto foo (H h,
enable_if_t<is_same<typename result_of<H(C)>::type, bool>::value>* = 0)
{
return [h] (D x) { return h (C {}); };
}

template <typename H>
auto foo (H h,
enable_if_t<is_same<typename result_of<H(D)>::type, bool>::value>* = 0)
{
return [h] (E x) { return h (D {}); };
}

现在我可以调用 foo 4 次,并将获得获取类型“E”参数的仿函数,最后调用带有参数“A”的内部处理程序:

auto inner_handler = [] (A) -> bool { return false; };
auto f = foo (foo (foo (foo ( inner_handler ))));
f (E {});

我想要的是实现 call_until 函数,该函数会递归调用“foo”重载,直到生成的仿函数的参数类型变为 T。

假设转换器从 A 到 E 的路径始终存在并且恰好是一个。换句话说,我想要表达

auto f = call_until<E> ( inner_handler );

完全一样工作

auto f = foo (foo (foo (foo ( inner_handler ))));

我从这样的事情开始:

template <typename Stop, typename Handler, typename Result>
struct call_until_helper
{
Handler handler_;
call_until_helper (Handler h) : handler (h) {}
};

template <typename Stop, typename Handler>
call_until_helper<Stop, Handler,
typename boost::function_traits<Handler>::result_type>
call_until (Handler handler)
{
return call_until_helper<Stop, Handler,
typename boost::function_traits<Handler>::result_type> (handler);
}

但是我遇到了编译错误并且有点卡在了这一点上。我需要一些想法来实现它。

在线代码:http://ideone.com/ZRFxnw

最佳答案

您最接近的问题是 function_traits 需要函数类型,而不是 lambda 类型。要确定这一点,只需找到错误,提取导致它的语句,剥离类型并直接将它们传递进去。

boost::function_traits< decltype( inner_handler ) >::result_type b = false;

编译失败。然后我检查了文档,是的,它需要一个函数类型,而不是 lambda。 Lambda 不是函数。


这是您实际问题附近的问题解决方案草图。语法有点不同,因为我很懒。

这里是fooify。它代表单个对象中 foo 的整个重载集:

struct fooify {
template<class...Args>
auto operator()(Args&&...args)const{
return foo(std::forward<Args>(args)...);
}
};

这是一种辅助类型,它递归地将操作应用于输入,直到通过测试为止:

template<class Action, template<class...>class test, class Arg, class=void>
struct repeat_until_helper {
using action_result = result_of_t< Action&(Arg) >;
auto operator()(Action&& action, Arg&&arg)const {
return repeat_until_helper<Action, test, action_result>{}(
std::forward<Action>(action),
action( std::forward<Arg>(arg) )
);
}
};
template<class Action, template<class...>class test, class Arg>
struct repeat_until_helper< Action, test, Arg,
std::enable_if_t< test<Arg>{} >
> {
auto operator()(Action&& action, Arg&&arg)const {
return std::forward<Arg>(arg);
}
};

这是一个使用了上面的helper的函数,所以我们只需要传入一个类型(测试),其余推导:

template<template<class...>class test, class Action, class Arg>
auto repeat_until( Action&& action, Arg&& arg) {
return repeat_until_helper< Action, test, Arg >{}( std::forward<Action>(action), std::forward<Arg>(arg) );
}

下面是对使用 E 右值调用的类型的测试:

template<class X, class=void>
struct can_be_called_with_E:std::false_type{};
template<class X>
struct can_be_called_with_E<X,
decltype(
void(
std::declval<X>()(std::declval<E>())
)
)
>:std::true_type{};

我们完成了。语法不同,但这只是一些需要整理的工作。

live example

关于c++ - 递归调用重载的c++函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28373514/

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