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

为什么一个常数可变的lambda不能自动

仲鸿风
2023-03-14
#include <type_traits>

int main()
{
    auto f1 = [](auto&) mutable {};
    static_assert(std::is_invocable_v<decltype(f1), int&>); // ok

    auto const f2 = [](auto&) {};
    static_assert(std::is_invocable_v<decltype(f2), int&>); // ok

    auto const f3 = [](auto&) mutable {};
    static_assert(std::is_invocable_v<decltype(f3), int&>); // failed
}

见演示

为什么常量可变lambda不能接受引用参数?

共有2个答案

姜乐家
2023-03-14

由于同样的原因,您会因此而出错:

struct foo {
    void operator()(){}
};

int main() {
    const foo f;
    f();
}

错误是:

<source>:7:5: error: no matching function for call to object of type 'const foo'
    f();
    ^
<source>:2:10: note: candidate function not viable: 'this' argument has type 'const foo', but method is not marked const
    void operator()(){}
         ^

因为不能在常量实例上调用非常量方法。Lambdas获得了正确的默认常量,因此如果没有mutable操作符()就是const。使用mutable时,操作符()是一个非常量方法,您不能调用常量f3

太叔超英
2023-03-14

这里有两件有趣的事情。

首先,lambda的调用操作符(模板)默认为const。如果您提供了mutable,那么它就不是const。在正常成员函数中,mutable对lambda的影响与trailingconst的影响完全相反(它不影响lambda捕获等)

所以如果你看这个:

auto const f3 = [](auto&) mutable {};
static_assert(std::is_invocable_v<decltype(f3), int&>); // failed

这是一个const对象,其调用操作符模板(因为它是一个通用lambda)是非const。因此,您不能调用它,原因与您不能在任何其他上下文中调用const对象上的非const成员函数相同。请看另一个答案。

第二,有人指出,尽管如此,这是可行的:

auto const f4 = [](int&) mutable {}; // changed auto& to int&
static_assert(std::is_invocable_v<decltype(f4), int&>); // now ok

这不是编译器错误。也不意味着我刚才说的是错的。f4仍然有一个非const调用操作符。不能调用,因为f4是一个const对象。

然而。

lambda还有一个有趣的方面没有捕获:它们有一个到函数指针类型的转换函数。也就是说,我们通常认为lambdaf4如下所示:

struct __unique_f4 {
    auto operator()(int&) /* not const */ { }
};

而且,如果这是整个故事,const__unique_f4确实不能用int调用

struct __unique_f4 {
    auto operator()(int&) /* not const */ { }

    // conversion function to the appropriate function
    // pointer type
    operator void(*)(int&)() const { /* ... */ }
};

我们有一条规则,当你调用一个对象,比如f(x)时,你不仅要考虑f的调用运算符--那些名为运算符()的成员--而且还要考虑f的代理调用函数--是否有任何函数指针可以将f转换为,然后调用。

在这种情况下,你可以!您可以将f4转换为space(*)(int

但这仍然意味着f4的调用操作符不是常量,因为您声明它是可变的。它没有说明是否可以使用mutablelambdas引用参数

 类似资料:
  • 这个问题与前一个问题相关,在前一个问题中,我们注意到init捕获lambdas与Boost的范围和迭代器不兼容,因为一些相当模糊且嵌套很深的故障可能很难通过破解Boost来解决。射程源。 接受的答案建议将lambda存储在对象中。为了避免潜在的函数调用开销,我编写了两个函数对象,可以作为潜在的解决方法。它们在下面的代码中被称为和 不使用和编译行,并正确打印行的的实例。 然而,标准草案提到 5.1.

  • 我在读关于不可变类的书,而使类不可变的方法据说是: 1-使类成为最终类以防止继承 我认为第三个条件是不必要的。当我们使一个变量最终并为它提供任何值时,在那之后,即使通过方法也不能给它赋值(因为一旦赋值给它,最终变量就不能改变)。那么为什么我们需要第三个条件没有setter方法呢? 我是不是理解错了?

  • 我很惊讶地看到这个程序甚至可以编译,但结果更让我惊讶: 交换功能在库中实现为: 其中是一个可变的Java列表,而不是不可变的静态编程语言列表。所以我认为其他Java函数也可以工作。例如: 工作,但其他函数,例如函数,甚至不编译: 生成以下错误消息: 类型推断失败:趣味填充(p0:可变列表!,p1:T!):无法将单位应用于(List,Int)类型不匹配:推断的类型为List,但为MutableLis

  • 本文向大家介绍String 为什 么是不可变的?相关面试题,主要包含被问及String 为什 么是不可变的?时的应答技巧和注意事项,需要的朋友参考一下 简单的来说:String 类中使用 final 关键字修饰字符数组来保存字符串,`private final char value[]`,所以 String 对象是不可变的。而StringBuilder 与 StringBuffer 都继承自 Ab

  • 问题内容: 我试图为对象类型分配一个lambda: 它给我一个错误的说法: 为什么会这样,怎么做? 问题答案: 这是不可能的。根据错误消息不是功能接口,即具有单个公共方法的接口,因此您需要使用引用类型,例如

  • 基本上,我试图用一个名为“a”的变量设置数组的长度,并将其声明为3和int。当我试图用for循环查看所有元素时,我不会将“null”作为元素。到现在为止,一直都还不错。然而,当有人想向该数组中添加一个元素时,我会向提到的变量“a”中添加1,从而延长该数组的长度,并允许我向该数组中再添加一个元素。但它不起作用。以下是代码: }