当前位置: 首页 > 知识库问答 >
问题:

推断Lambda捕获类型

闾丘成礼
2023-03-14

我最近发现,通过lambda中的值捕获常量对象,意味着labmda主体(即lambda的数据成员)中的变量也是常量
例如:

const int x = 0;
auto foo = [x]{
  // x is const int
};

§8.1中提到了这种行为。5.2在C 17草案中:

对于通过复制捕获的每个实体,在闭包类型中声明一个未命名的非静态数据成员。未指定这些成员的声明顺序。如果实体是对对象的引用,则此类数据成员的类型为引用类型;如果实体是对函数的引用,则为对引用函数类型的左值引用;或者以其他方式为相应捕获实体的类型。匿名工会的成员不得被复制。

我希望推断捕获变量的类型与推断自动变量的类型相同
对捕获的类型使用不同的类型推断规则是否有充分的理由?

共有3个答案

孙俊彦
2023-03-14

原因是lambda中的operator()默认为const

int main()
{
    const int x = 0;
    auto foo = [x](){}; // main::$_0::operator()() const
    foo();
}

因此,您必须使用mutablelambda:

int main()
{
    const int x = 0;
    auto foo = [x=x](){}; // main::$_0::operator()()
    foo();
}
酆茂才
2023-03-14

不是对推理的回答;这里已经有了一个全面的答案。

对于那些想知道如何捕获常量变量的非常量副本的人,您可以使用带有初始化器的捕获:

const int x = 0;
auto foo = [x = x]() mutable {
    // x is non-const
};

但这需要C 14。与C 11兼容的解决方案是在lambda之外制作副本:

const int x = 0;
int copy = x;
auto foo = [copy]() mutable {
    // copy is non-const
};
计向晨
2023-03-14

在您的示例中,不可能修改x,因为lambda不是可变的,这使得函数调用操作符常量。但是,即使lambda是可变的,引用的段落确实在lambdaconst int中创建了x类型。

如果我没记错的话,这是C 11中的一个深思熟虑的设计决策,目的是使lambda中的x的使用行为类似于封闭作用域中的x的使用。那就是,

void foo(int&);
void foo(const int&);
const int x = 0;
foo(x);  // calls foo(const int&)
auto foo = [x]() mutable {
    foo(x);  // also calls foo(const int&)
};

这有助于避免错误,例如,某些代码从显式循环重写为使用lambda调用标准库算法。

如果我记错了,希望有正确答案的人会介入并写下他们自己的答案。

 类似资料:
  • 我在Haskell编程中的冒险并不都是史诗般的。我正在实现简单的Lambda演算,我很高兴完成了、以及,希望它们是正确的。剩下的是,就像红色框中定义的那样(在下图中),我正在为此寻找指导。 如果我说错了请指正, (1)但是我发现返回给定变量的类型。Haskell中的什么构造返回?我知道在中是,但我正在寻找一个在下工作的。 (3)对于(T-APP)和(T-ABS),我假设我分别对和应用程序应用了替换

  • 我在Java 8中试验新的lambda,我正在寻找一种方法,在lambda类上使用反射来获得lambda函数的返回类型。我对lambda实现通用超接口的情况特别感兴趣。在下面的代码示例中, 到泛型类型参数T。 即使对于本身是泛型的子类,如果已知其他一些泛型参数,也有某些方法可以找出与泛型参数绑定的内容。考虑下例中的情况2,IdentityMapper,其中F和T都绑定到同一类型。当我们知道时,如果

  • 这是我课堂的一部分: 我想访问Lambda的私有成员变量output_文件,它位于公共成员函数dump_dvars中。当我捕获this指针时,我无法访问该变量,因为它是私有的,但我也不想将其公开!我已经读过这个问题(如何让lambda成为一个类的朋友?)但我不想创建另一个函数。因此,我目前解决这个问题的方法是创建对私有成员的引用,并通过引用捕获列表将该变量传递给我的Lambda。 这是一个好的解决

  • 主要内容:1 Java8 类型推断的介绍,2 Java8 类型推断的案例1,3 Java8 类型推断的案例21 Java8 类型推断的介绍 类型推断是Java的一项功能,它使编译器可以查看每个方法调用和相应的声明以确定参数的类型。 Java在Java 8中提供了类型推断的改进版本。 1.1 Java8以前 在下面的声明中,我们在一侧提到了arraylist的类型。这种方法是在Java 7中引入的。在这里,您可以将第二面留为<>,并且编译器将通过引用变量的类型来推断其类型。 1.2 Java8以后

  • TypeScript 类型检查机制包含三个部分: 类型推断 类型保护 类型兼容性 本节介绍其中的类型推断,类型推断主要用于那些没有明确指出类型的地方帮助确定和提供类型,这是 TypeScript 的一种能力。 类型推断是有方向的,要注意区分从左向右和从右向左两种推断的不同应用。 1. 慕课解释 类型推断的含义是不需要指定变量类型或函数的返回值类型,TypeScript 可以根据一些简单的规则推断其