据我所知-通用lambda通过operator()
模板化为本地作用域结构的对象。这使通用Lambda非常强大且易于使用。另一方面,当结构具有模板成员时,可以创建嵌套在函数中的结构,例如:
#include <iostream>
int main() {
struct inner {
template <class T>
void operator()(T &&i) { }
};
return 0;
}
或单独模板化:
int main() {
template <class T>
struct inner {
void operator()(T &&i) { }
};
return 0;
}
编译器似乎在编译时有问题:
我认为问题出在c++标准,而不是编译器bug。允许lambda具有模板成员而不是本地结构的原因是什么?
我找到了this qustion,但是我认为答案有点过时了(即使对于c++ 11,我也不认为这是真的)。
最佳答案
这是core issue 728,它是在通用lambda成为事物之前提交的。
您提到了通用lambda,它们与具有相应成员template operator()
的本地类相同。但是,它们实际上不是,并且差异与实现特征有关。考虑
template <typename T>
class X {
template <typename>
void foo() {
T t;
}
};
和
template <typename T>
auto bar() {
return [] (auto) {T t;};
};
在第一种情况下,使用
<void>
实例化这些模板是可以的,但在第二种情况下,格式不正确。在第一种情况下为什么会罚款? foo
不必对于每个特定的T
都可实例化,而仅是其中之一(即[temp.res]/(8.1))。为什么在第二种情况下格式错误?使用提供的模板参数部分实例化通用lambda的主体。这种部分实例化的原因是……
(Richard Smith)我们必须实例化足够多的本地"template"以使其独立于本地上下文(其中包括封闭函数模板的模板参数)。
这也与
[expr.prim.lambda]/13,它强制一个实体在以下情况下被lambda隐式捕获:
也就是说,如果我有一个像
[=] (auto x) {return (typename decltype(x)::type)a;}
这样的lambda,其中a
是封闭函数中的某个块范围变量,无论x
的成员typedef是否适用于void
,强制转换都会导致a
的捕获,因为我们必须无需等待lambda的调用就可以决定。有关此问题的讨论,请参见original proposal on generic lambdas。最重要的是,成员模板的完全推迟实例化与(至少一个)主要实现所使用的模型不兼容,并且由于这些是预期的语义,因此未引入该功能。
这是这种限制的最初动机吗?它是在1994年1月到1994年5月之间的某个时间引入的,没有论文涉及,因此我们只能从this paper证明为什么本地类不应作为模板参数的理由中大致了解流行的概念:
也许那时,有人想去KISS。
关于c++ - 为什么不允许带模板方法的嵌套结构的泛型lambda?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40242505/