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

问题描述 投票:3回答:2

我正在尝试函数式编程,我写了这篇文章。

[=](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只需要ints,但是p需要是一个LambdaType<LambdaType<int>>来接受q但是当你将p改为LambdaType<LambdaType<int>>时,p只接受LambdaType<int>但p不是LambdaType<int>,它需要是一个LambdaType<LambdaType<LambdaType<int>>>接受p。

那么,p是什么类型的?

哦顺便说一句,这是我关于stackoverflow的第一个问题

c++ lambda auto
2个回答
2
投票

那么,我们正在寻找四种类型PQRS,例如:

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

QS只不过是占位符参数和返回类型,所以我们不需要任何东西:

struct Q { };
struct S { };

PR更有趣,因为在他们需要的签名规范中有一个循环:R既是P的调用的结果,又能够用另一个P调用。这使得无法使用函数类型或lambda类型进行声明,而函数类型或lambda类型仅由它们(此处为无限递归)签名定义。

但是C ++可以使用仿函数轻松地对其进行排序 - 只需给出一个名称,并且在简单的前向声明的帮助下,您可以创建循环仿函数:

struct P;

struct R {
    S operator()(P) const;
};

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

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

Live demo on Coliru


最后,C ++有模板,这使我们有能力用最无聊的解决方案解决这个问题:

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

这样一个O只会吞下你称之为的东西,甚至是它本身的一个例子,甚至不关心。

Live demo on Coliru


1
投票

实施水平

c++,Lambda是用structoperator()实现的,auto的名字不详。因为关键字template在这里意味着类型是通用的,所以需要'a。您必须通过给出struct模板的参数来显式实例化struct,然后可以确定'bp(q)(p); ↑ 代表什么。

抽象层次

p

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

  • 'b是参数的类型
  • p(q)(p); ↑ 是返回类型

'b

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

std::function<int(int)> factorial = [&](int a) {return a == 1 ? 1 : a*factorial(a-1);}; 之类的trival递归函数不同:

Factorial
  • 对于Factorial:它的返回类型仍然不依赖于类型(p)本身。
  • 对于p:它的返回类型依赖于qazxswpois类型。所以类型是无限的。

就像@ molbdnilo的评论一样:

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

© www.soinside.com 2019 - 2024. All rights reserved.