为什么允许使用通用 lambda,而不允许使用具有模板化方法的嵌套结构?
Why generic lambdas are allowed while nested structs with templated methods aren't?
据我所知-泛型lambdas被转换为局部作用域结构的对象与模板化的operator()
。这使得泛型lambda非常强大和易于使用的工具。另一方面,可以创建嵌套到函数中的结构体,但是该结构体具有模板化的成员,例如:
#include <iostream>
int main() {
struct inner {
template <class T>
void operator()(T &&i) { }
};
return 0;
}
or被自己模板化:
int main() {
template <class T>
struct inner {
void operator()(T &&i) { }
};
return 0;
}
编译器在编译它时似乎有问题:
error: invalid declaration of member template in local class
和
error: a template declaration cannot appear at block scope
我认为问题更多地在于c++标准而不是编译器错误。什么原因允许lambda有模板化的成员而不是局部结构?
我发现了这个问题,但我认为答案有点过时了(我不认为这是真的,即使是c++11)。
这是核心问题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的主体(部分地)。这个部分实例化的原因是…
处理函数定义时使用的词法作用域基本上是暂时的,这意味着很难支持延迟函数模板定义的某些部分的实例化。我们必须实例化足够的局部"模板",使其独立于局部上下文(其中包括封闭函数模板的模板参数)。
这也与基本原理有关[expr.prim。/13,它规定如果一个实体…
在潜在求值表达式([basic.def.odr])中命名实体,其中封闭的完整表达式依赖于在lambda表达式的可达范围内声明的泛型lambda参数。
也就是说,如果我有一个像[=] (auto x) {return (typename decltype(x)::type)a;}
这样的lambda,其中a
是来自封闭函数的块作用域变量,不管x
的成员类型是否为void
,强制转换将导致捕获a
,因为我们必须在不等待lambda调用的情况下决定这一点。有关此问题的讨论,请参阅泛型lambda的原始提案。
底线是,完全推迟成员模板的实例化与(至少一个)主要实现所使用的模型不兼容,并且由于这些是预期的语义,因此没有引入该特性。
这是这个约束的原始动机吗?它是在1994年1月到5月之间的某个时候被引入的,没有论文涉及它,所以我们只能从这篇论文中对为什么局部类不能作为模板参数的论证中得到一个大致的流行概念:
类模板和从模板生成的类是全局作用域实体,不能引用局部作用域实体。
也许在那个时候,一个人想要接吻。
我认为问题更多地出在c++标准
正确的。这在类模板的[temp]中有规定:
模板声明只能作为命名空间作用域或类作用域声明出现。
和[temp.mem]的成员模板:
非闭包类型的局部类不能有成员模板。
为什么lambda可以有模板化的成员而不是局部结构?
因为一旦我们在c++ 11中有了lambda,我们就认为将这个概念扩展为泛型lambda是非常有用的。有一项关于这种语言扩展的建议,经修订和修订并通过。
另一方面,目前还没有一个提案(据我从一个简短的搜索中了解到)提出了在局部类中需要成员模板的动机,而泛型lambda不能充分解决这个问题。
如果你觉得这是一个需要解决的重要问题,在提出一个深思熟虑的动机来说明为什么本地成员模板很重要之后,可以自由提交一个提案。
- 通过方法访问结构
- 有什么方法可以遍历结构吗
- 没有为自己的结构调用列表推回方法
- 在 c++ 中拥有一组结构的正确方法是什么?
- 如何在方法中传递结构参数
- 对结构方法的未定义引用
- 不同的类或结构初始化方法之间的性能差异是什么?
- 让编译器告诉什么确切的纯虚拟方法使结构抽象?
- 我想直接在结构中插入,但没有一种方法可以正确避免填充问题
- 在C++中更改结构内部元素的方法?
- 学习数据结构和算法的简单方法
- 类方法 - 数据结构中 For 循环的运行时错误
- 如何从 node-ffi 调用 c++ 中以结构向量作为参数的方法?
- 哪一个是最好的方法类或结构?在 C++ 中
- 将一种数据类型的向量复制到同一数据类型的结构向量中的有效方法是什么
- 结构/方法不起作用
- 删除父/子窗口层次结构的最佳方法
- 任何方法都可以在C++中比较数据结构中的许多方法
- 具有重载方法的可变参数数据结构
- 成员初始化列表?合成方法?结构/数组编译问题