gpt4 book ai didi

c++ - 编译器如何以不同于常规函数的方式对待 lambda?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:46:29 26 4
gpt4 key购买 nike

我想知道编译器如何处理 lambda 函数而不是常规函数。即使排除捕获列表,正如我认为的那样,它的行为似乎也略有不同。

例如,我在上一篇文章中使用的 Trying to pass a constexpr lambda and use it to explicitly specify returning type ,我使用了一个 constexpr lambda 并将其作为常规函数参数传递。我引用了部分答案。

Parameters to constexpr functions are not themselves constexpr objects - so you cannot use them in constant expressions.

template <typename Lambda_T>
constexpr static auto foo(Lambda_T l) {
return std::array<event, (l())>{};
}
// Compiles with GCC (C++17), though ill-formed (according to the answer of my last post)

不过,引起我注意的是,这确实编译通过了 constexpr lambda,但没有编译通过了 constexpr 常规(全局)函数。是什么导致了这种差异?常规函数和 lambda 函数之间的编译器行为是否存在其他差异?

编辑:Lambda 实现示例

foo([](){ return 4; }); // C++17 Lambda's are implicitly constexpr

在这种情况下,lambda 基本上是值的包装器。

编辑:全局函数

无论何时传递一个全局函数,编译器都会提示——与使用 lambda 相反——这个函数,无论它是否被定义为 constexpr,都不能在常量条件下使用:

prog.cc:8:20: error: 'l' is not a constant expression

最佳答案

从您的代码段中删除一些无关的东西,我们得到

template<typename T>
constexpr void foo(T t)
{
constexpr int i = t();
}

constexpr int f() { return 42; }
auto l = []{ return 42; }

备注:

  1. 您正在尝试将 t() 用作 foo 中的 constexprfoo 实际上可以是一个普通函数,并且仍然表现相同。

  2. lambda 不是函数。它是一个带有 operator() 的匿名结构。

    struct L { constexpr int operator()() const { return 42; } };

    Tfoo(l) 调用中被推断为等同于 L 的类型。

  3. Tfoo(f) 调用中被推导为 int(*)()

  4. 在这两种情况下,t 不是 foo 中的constexpr。


来自 [expr.const]

An expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine, would evaluate one of the following expressions: [...]

  • an lvalue-to-rvalue conversion unless [...]

    • a non-volatile glvalue that refers to a non-volatile object defined with constexpr, or that refers to a non-mutable subobject of such an object, or

    • a non-volatile glvalue of literal type that refers to a non-volatile object whose lifetime began within the evaluation of e;

通过 int(*)() 调用需要左值到右值的转换。 t 不是用 constexpr 定义的对象,它的生命周期也不是在 t() 的计算中开始的。因此 t() 不是 foo(f) 中的 constexpr

调用 operator() 不需要左值到右值的转换。由于没有成员访问权限,因此它只是一个 constexpr 函数调用。因此 t()foo(l) 中的 constexpr

one more step从核心常量表达式到常量表达式,但对于此处的讨论并不重要。

关于c++ - 编译器如何以不同于常规函数的方式对待 lambda?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54387501/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com