首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么不能调用具有auto&参数的const可变lambda?

为什么不能调用具有auto&参数的const可变lambda?
EN

Stack Overflow用户
提问于 2021-12-10 19:00:39
回答 2查看 1.1K关注 0票数 28
代码语言:javascript
复制
#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
}

请参阅演示

为什么一个不可变的λ不能接受一个引用参数?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-12-10 19:25:30

这里有两件有趣的事情。

首先,默认情况下,lambda的调用操作符(模板)是const。如果您提供mutable,那么它不是constmutable对lambda的影响与正常成员函数中跟踪const的效果完全相反(它不影响lambda捕获等)。

所以如果你看看这个:

代码语言:javascript
复制
auto const f3 = [](auto&) mutable {};
static_assert(std::is_invocable_v<decltype(f3), int&>); // failed

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

第二,有人指出,这是可行的:

代码语言:javascript
复制
auto const f4 = [](int&) mutable {}; // changed auto& to int&
static_assert(std::is_invocable_v<decltype(f4), int&>); // now ok

这不是编译器的错误。也不意味着我刚才说的是错的。f4仍然有一个非const呼叫运营商.因为f4是一个const对象,所以不能调用它。

然而。

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

代码语言:javascript
复制
struct __unique_f4 {
    auto operator()(int&) /* not const */ { }
};

而且,如果这是整个故事的话,const __unique_f4确实不能用int&来调用。但实际上看起来是这样的:

代码语言:javascript
复制
struct __unique_f4 {
    auto operator()(int&) /* not const */ { }

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

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

在这种情况下,你可以!您可以将f4转换为void(*)(int&),并且可以用int&调用该函数指针。

但这仍然意味着f4的呼叫运算符不是const,因为您声明它是可变的,而且它也没有说明是否可以让mutable lambda接受引用参数。

票数 32
EN

Stack Overflow用户

发布于 2021-12-10 19:09:17

由于同样的原因,您会得到一个错误:

代码语言:javascript
复制
struct foo {
    void operator()(){}
};

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

错误是:

代码语言:javascript
复制
<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()(){}
         ^

因为不能在const实例上调用非const方法。Lambda获得了默认的常数,因此如果没有mutableoperator()就是const。对于mutableoperator()是一个不能调用const f3;的非const方法。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70309251

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档