代码之家  ›  专栏  ›  技术社区  ›  xmllmx

为什么不能调用带有auto&参数的常量可变lambda?

  •  11
  • xmllmx  · 技术社区  · 4 年前
    #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
    }
    

    demo

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

    2 回复  |  直到 4 年前
        1
  •  11
  •   Barry    4 年前

    这里有两件有趣的事情。

    const 默认情况下。如果你提供 mutable 那就不是了 常数 易变的 在lambda上是 唯一地 常数 在正常成员函数中(不影响lambda捕获等)

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

    这是一个 对象,其调用运算符模板(因为它是通用lambda)为非- 常数 . 所以你不能调用它,因为同样的原因你不能调用非- 对象在任何其他上下文中。看见 this other answer

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

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

    不 编译器错误。 也没有 f4 还 非常量 呼叫接线员。你不能调用它,因为 是一个常量对象。

    然而

    就像这样:

    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 的调用运算符--名为 operator() F 的 surrogate call functions --有没有可以转换的函数指针 F 到,然后调用。

    在这种情况下,你可以!你可以转换 到 void(*)(int&) 并且该函数指针是可调用的 国际及; .

    f4 的调用运算符不是常量,因为您声明它是可变的。它也没有说你是否可以 lambda采用参考参数。

        2
  •  7
  •   463035818_is_not_an_ai    4 年前

    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()(){}
             ^
    

    mutable operator() 是 const . 具有 易变的 是一个非常量方法,不能在 const f3;