这个 lambda 的参数是什么类型?

What type is this lambda's parameter?

本文关键字:类型 是什么 参数 lambda 这个      更新时间:2023-10-16

我正在尝试功能编程,我写了这篇文章。

[=](auto p) { 
    return [=](auto q) { 
        return p(q)(p); 
    }; 
})

我开始想知道这是怎么可能的,P?

的类型是什么

所以,我写了这样的东西。

template<class Type>
using LambdaType = std::function<std::function<Type(Type)>(Type)>;

[=](LambdaType<int> p) {
    return [=](LambdaType<int> q) {
        return p(q)(p);
    };
}

编译时,编译器会给我错误。

error C2664: 'std::function<Type (int)> std::_Func_class<_Ret,int>::operator ()(int) const': cannot convert argument 1 from 'std::function<std::function<Type (int)> (int)>' to 'int'
error C2664: 'main::<lambda_cec7eb77d9cd29f3c40710200090f154>::()::<lambda_b8db28542cb51159223ad8d89c63d794>::()::<lambda_224126017af42fcee190e88f299089fc>::()::<lambda_415db9fd88f1008b25af42ccb33b1c77> main::<lambda_cec7eb77d9cd29f3c40710200090f154>::()::<lambda_b8db28542cb51159223ad8d89c63d794>::()::<lambda_224126017af42fcee190e88f299089fc>::operator ()(std::function<std::function<Type (std::function<std::function<int (int)> (int)>)> (std::function<std::function<int (int)> (int)>)>) const': cannot convert argument 1 from 'main::<lambda_cec7eb77d9cd29f3c40710200090f154>::()::<lambda_b8db28542cb51159223ad8d89c63d794>::()::<lambda_fa72c454c823301ba6dfa9cba6f558e0>' to 'std::function<std::function<Type (std::function<std::function<int (int)> (int)>)> (std::function<std::function<int (int)> (int)>)>'

但这是我意识到P仅接收INT的时候,但是P是LambdaType<LambdaType<int>>才能吸入Q但是,当您将P更改为LambdaType<LambdaType<int>>时,P仅接收LambdaType<int>,而P则不是LambdaType<int>,并且需要是LambdaType<LambdaType<LambdaType<int>>>才能参加p。

那么,P?

什么类型

哦,顺便说一句,这是我在Stackoverflow上的第一个问题

好吧,我们正在寻找四种类型PQRS,例如:

  • P(Q) -> R
  • R(P) -> S

QS不仅仅是占位符和返回类型,因此我们不需要任何东西:

struct Q { };
struct S { };

PR更有趣,因为他们需要的签名规范中有一个循环: R既是P调用的结果,并且可以与另一个P调用。这使得无法使用功能类型或lambda类型声明,这仅由其(此处无限递归)签名定义。

但是C 可以很容易地用函子对其进行整理 - 只要给出一个名称,借助简单的前向功能,您可以很好地创建loopopy functor:

struct P;
struct R {
    S operator()(P) const;
};
struct P {
    R operator()(Q) const { return {}; }
};
inline S R::operator()(P) const { return {}; }

coliru上的现场演示


最后,C 具有模板,这使我们有能力用有史以来最无聊的解决方案解决此问题:

struct O {
    template <class T>
    O const &operator()(T) const { return *this; }
};

这样的O只会吞下任何您称之为的情况,甚至是本身的实例,甚至不在乎。

coliru上的现场演示

实现级别

c++中,Lambda用structoperator()实现,其名称未知。因为此处的关键字auto意味着类型是通用的,因此需要template。您必须通过给出结构模板的参数来明确实例化结构,然后可以确定'a'b代表的内容。

抽象级别

p(q)(p);
  ↑

假设p的类型是'a->'b

  • 'a是参数的类型
  • 'b是返回类型

p(q)(p);
     ↑

我们可以看到返回类型('b)可以接收p,该类型为'a->'b,因此我们可以用'a->'b替换'b。问题解决了吗?否!

factorial这样的三个递归函数不同:

std::function<int(int)> factorial = [&](int a) {return a == 1 ? 1 : a*factorial(a-1);};
  • 对于Factorial:其返回类型仍然不依赖于类型(Factorial)本身。
  • 对于p:其返回类型依赖于p S类型。因此类型是无限的。

就像 @molbdnilo的评论一样:

它具有无限类型,无法实例化。