constexpr 与 lambda 表达式的 C++ 用法

ggu*_*lia 4 c++ lambda constexpr c++17

我正在阅读C++17 - The Complete Guide 一书,在constexprlambda 的6.1 节中,作者给出了两个例子:

auto squared1 = [](auto val) constexpr { // example 1. compile-time lambda calls
  return val * val;
};
Run Code Online (Sandbox Code Playgroud)

constexpr auto squared2 = [](auto val) { // example 2. compile-time initialization
  return val * val;
};
Run Code Online (Sandbox Code Playgroud)

并说这两个彼此不同,因为示例 1在编译时评估,示例 2在编译时初始化。


然后作者做了以下我不完全理解的陈述:

如果(仅)lambda 是constexpr它可以在编译时使用,但是如果由 lambda 初始化的(闭包)对象是constexpr,则该对象在程序启动时被初始化,但 lambda 可能仍然是一个只能在以下情况下使用的 lambda运行时(例如,使用静态变量)。因此,您可以考虑声明:

constexpr auto squared = [](auto val) constexpr { // example 3
  return val * val;
};
Run Code Online (Sandbox Code Playgroud)

上面的说法究竟是什么意思?

很明显,在示例 3中,constexpr关键字出现在squared2lambda 对象的初始化语句和 lambda 表达式本身上,但我不明白这与示例 1相比有什么优势。

ein*_*ica 6

问题是,一个auto-declared 的对象不采用constexpr它的初始化表达式的'ness,只采用它的类型;并且constexpr该类型的一部分。看:

为什么`auto` 不采用其初始化表达式的constexpr'ness?

所以,假设我有:

auto five_squared = 25;
Run Code Online (Sandbox Code Playgroud)

值 25 非常多constexpr,即它可以在编译时使用。然而 -在编译时five_squared不可用。您仍然需要指出它是constexpr(*)。

它与您的 lambda 基本相同。一个 lambda 是一个现场定义的类的实例,带有operator(). 如果你自己不让它squared成为一个constexpr变量,那么关于它的任何东西都不会成为一个变量。


(*) - 请注意,由于 C++ 语言中的特殊规则,const使用常量表达式初始化的整数是自动的constexpr,因此您可以直接编写const autoconstexpr隐式获取。然而,这是一个需要记住的棘手的特殊情况,所以如果你想创建一个变量,constexpr我建议你明确说明它。感谢@cigien 提出这一点。