我正在尝试函数式编程,我写了这篇文章。
[=](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只接受整数时,但p必须是LambdaType<LambdaType<int>>
才能接受q
但是当你将p更改为LambdaType<LambdaType<int>>
时,p只会接收LambdaType<int>
,但p不是LambdaType<int>
,而p需要LambdaType<LambdaType<LambdaType<int>>>
。
那么,p是什么类型的?
哦顺便说一句,这是我关于stackoverflow的第一个问题
答案 0 :(得分:2)
好吧,我们正在寻找四种类型P
,Q
,R
,S
,例如:
P(Q) -> R
R(P) -> S
Q
和S
只不过是占位符参数和返回类型,因此我们不需要任何内容:
struct Q { };
struct S { };
P
和R
更有趣,因为在他们需要的签名规范中有一个循环:R
都是调用{{1}的结果},并且能够使用另一个P
进行调用。这使得无法使用函数类型或lambda类型进行声明,这些类型仅由它们(此处是无限递归)签名定义。
但是C ++可以使用仿函数轻松地对其进行排序 - 只需给出一个名称,并且在简单的前向声明的帮助下,您可以创建循环仿函数:
P
最后,C ++有模板,这使我们有能力用最无聊的解决方案解决这个问题:
struct P;
struct R {
S operator()(P) const;
};
struct P {
R operator()(Q) const { return {}; }
};
inline S R::operator()(P) const { return {}; }
这样的struct O {
template <class T>
O const &operator()(T) const { return *this; }
};
只会吞下你所称之为的任何东西,甚至是它本身的一个实例,甚至不关心。
答案 1 :(得分:1)
在c++
中,Lambda是使用struct
operator()
实现的,其名称未知。由于此处的关键字auto
表示类型是通用的,因此需要template
。您必须通过为结构模板提供参数来显式实例化结构,然后可以确定'a
和'b
代表的内容。
p(q)(p);
↑
假设p
的类型为'a->'b
'a
是参数的类型'b
是返回类型p(q)(p);
↑
我们可以看到返回类型('b
)可以收到p
,其类型为'a->'b
,因此我们可以将'b
替换为'a->'b
。这个问题解决了吗?不!
与trival递归函数不同,如factorial
:
std::function<int(int)> factorial = [&](int a) {return a == 1 ? 1 : a*factorial(a-1);};
Factorial
:其返回类型仍然不依赖于类型(Factorial
)本身。 p
:其返回类型依赖于p
类型。所以类型是无限的。 就像@ molbdnilo的评论一样:
它具有无限类型,无法实例化。