gpt4 book ai didi

c++ - 如何管理需要从递归仿函数/lambda 派生的模板参数的声明?

转载 作者:行者123 更新时间:2023-12-05 09:06:27 24 4
gpt4 key购买 nike

我正在尝试构建一个干净整洁的具有递归能力的 lambda 自作用域实现(它基本上是一个 Y 组合器,尽管我认为在技术上不完全是)。这是一个带我去的旅程,除此之外,this threadthis threadthis thread .

我已经尽可能清楚地归结了我的一个问题:我如何传递将 lambda 作为模板参数的模板仿函数?

#include <string>
#include <iostream>
#define uint unsigned int

template <class F>
class Functor {
public:
F m_f;

template <class... Args>
decltype(auto) operator()(Args&&... args) {
return m_f(*this, std::forward<Args>(args)...);
}
};
template <class F> Functor(F)->Functor<F>;

class B {
private:
uint m_val;
public:
B(uint val) : m_val(val) {}
uint evaluate(Functor<decltype([](auto & self, uint val)->uint {})> func) const {
return func(m_val);
}
};

int main() {
B b = B(5u);
Functor f = Functor{[](auto& self, uint val) -> uint {
return ((2u * val) + 1u);
}};

std::cout << "f applied to b is " << b.evaluate(f) << "." << std::endl;
}

上面的代码不起作用,Visual Studio 声称 f(在 b.evaluate(f) 调用中)与参数类型不匹配。

我的假设是 auto & self 不够聪明,无法完成这项工作。我该如何解决这个问题?当它们基本上无法定义时,我如何存储和传递这些东西?这就是为什么我见过的许多 Y 组合器实现都有奇怪的双重包装的原因吗?

如有任何帮助或解释,我们将不胜感激。

最佳答案

我看到的唯一方法是使 evaluate() 成为模板方法;如果你想确保收到一个 Functor(但你可以简单地接受一个可调用对象:参见 Yakk's answer ):

template <typename F>
uint evaluate(Functor<F> func) const {
return func(m_val);
}

考虑到每个 lambda 都是不同的类型,因为您可以使用以下简单代码进行验证

auto l1 = []{};
auto l2 = []{};

static_assert( not std::is_same_v<decltype(l1), decltype(l2)> );

因此,将特定的 lambda 类型强加给 evaluate() 是行不通的,因为如果您使用(显然)相同的 lambda 函数调用该方法,调用将不匹配,如您所见在下面的例子中

auto l1 = []{};
auto l2 = []{};

void foo (decltype(l1))
{ }

int main ()
{
foo(l2); // compilation error: no matching function for call to 'foo'
}

关于c++ - 如何管理需要从递归仿函数/lambda 派生的模板参数的声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66067390/

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