[英]Why does each instantiation of a lambda function result in a unique type?
Recently I asked a question about some code I had which was causing my compiler to run out of heap space.最近我问了一个关于我的一些代码的问题,这些代码导致我的编译器耗尽了堆空间。 This code contained a recursive template function which was being passed a lambda function.
此代码包含一个递归模板函数,该函数被传递给一个 lambda 函数。 Each instantiation of the template function caused (via the recursive call) another instantiation of the same template function with it's lambda function parameter.
模板函数的每个实例化都导致(通过递归调用)使用它的 lambda 函数参数对同一模板函数进行另一个实例化。 It was explained that each instantiation of the lambda function results in a unique type, so an infinite loop of instantiations results and the compiler runs out of heap.
有人解释说,lambda 函数的每个实例化都会产生一个唯一的类型,因此会导致实例化的无限循环,并且编译器会耗尽堆。 Note that the logic of the program is such that there would be no infinite loop at runtime.
请注意,程序的逻辑是在运行时不会出现无限循环。
Here's an example of the code, this code does not compile on any of the major compilers.这是代码示例,此代码无法在任何主要编译器上编译。 This code is a heavily cut down version of my real code, it's just for illustrative purposes.
这段代码是我真实代码的大幅缩减版本,仅用于说明目的。
struct Null
{
template <typename SK>
static int match(int n, SK sk)
{
return 0;
}
};
template <typename T>
struct Repetition
{
template <typename SK>
static int match(int n, SK sk)
{
return T::match(0, [n]() { return match(0, [n](){ return n; }); });
}
};
int main()
{
using Test = Repetition<Null>;
Test::match(0, [](){ return 0; });
}
When this was explained it occurred to me that I could break the infinite loop by using a functor instead of a lambda function, since each instantiation of a the functor would not be a unique type.当解释这一点时,我突然想到我可以通过使用仿函数而不是 lambda 函数来打破无限循环,因为仿函数的每个实例化都不是唯一的类型。 Here's that code, this compiles fine
这是代码,编译得很好
struct Null
{
template <typename SK>
static int match(int n, SK sk)
{
return 0;
}
};
template <typename T>
struct Repetition
{
template <typename SK>
static int match(int n, SK sk)
{
return T::match(0, [n]() { return match(0, RepetitionSK<T>(n)); });
}
};
template <typename T>
struct RepetitionSK
{
RepetitionSK(int n) : n(n) {}
int operator()() { return n; }
int n;
};
int main()
{
using Test = Repetition<Null>;
Test::match(0, [](){ return 0; });
}
EDIT [=] captures have been replaced by the more explicit [n]
EDIT [=] 捕获已被更明确的 [n] 取代
My question is that why do lambda functions behave this way?我的问题是,为什么 lambda 函数会这样? The lambda functions in
Repetition::match
do not depend the template parameter SK
in any way. Repetition::match
中的 lambda 函数不以任何方式依赖模板参数SK
。 What's the benefit in having each instantiation of a lambda function result in a unique type?让 lambda 函数的每个实例化都产生唯一类型有什么好处?
Another question, is it possible to write this code using only lambda functions, no functors or other auxiliary classes?另一个问题,是否可以仅使用 lambda 函数而不使用仿函数或其他辅助类来编写此代码?
The question is more easily answered by considering the opposite.通过考虑相反的情况,这个问题更容易回答。 If it were not true, then some lambda's would have the same type.
如果它不是真的,那么一些 lambda 将具有相同的类型。 Furthermore, the Standard should then say which lambda's have the same type, and which lambda's have distinct types.
此外,标准应该说明哪些 lambda 具有相同的类型,哪些 lambda 具有不同的类型。
Note that with "type" we mean more than just the signature of operator()
.请注意,“类型”不仅仅意味着
operator()
的签名。 Lambda's have real type, eg they've got a sizeof
(which has to include the captured state). Lambda 有真实的类型,例如它们有一个
sizeof
(必须包括捕获的状态)。
For that reason, you can't just define the type in terms of tokens;出于这个原因,您不能只根据标记来定义类型; the token
T
may be the same but the meaning varies across instantiations.令牌
T
可能相同,但含义因实例而异。
This idea isn't entirely unique;这个想法并不完全是独一无二的。 non-inline functions are also unique even if they contain the exact same tokens (but then the function type will be the same - the correspondence isn't exact. And functions don't have a
sizeof
)非内联函数也是唯一的,即使它们包含完全相同的标记(但函数类型将相同 - 对应关系不准确。并且函数没有
sizeof
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.