C++中使用lambda表达式的constexpr

12

我正在阅读书籍《C++17完全教程》,在第6.1节中讲到了constexpr lambda,作者给出了两个示例:

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

and

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

并表示这两者不同,因为示例1在编译时进行评估,而示例2在编译时进行初始化。


接下来作者提出了以下几点声明,我并不完全理解:

If (only) the lambda is constexpr it can be used at compile time, but If the (closure) object initialized by the lambda is constexpr, the object is initialized when the program starts but the lambda might still be a lambda that can only be used at run time (e.g., using static variables). Therefore, you might consider declaring:

constexpr auto squared = [](auto val) constexpr { // example 3
  return val * val;
};

以上语句的确切含义是什么?

显然,在squared2 lambda对象的初始化语句和 lambda表达式本身中,constexpr关键字出现在示例 3中,但我不理解这与示例 1相比有何优势。

1个回答

10
事实上,使用auto声明的对象仅仅继承其初始化表达式的类型,而不是constexpr属性;并且constexpr不是该类型的一部分。详见:为什么`auto`不能继承其初始化表达式的constexpr属性? 因此,假设我有以下代码:
auto five_squared = 25;

值 25 非常 "constexpr",即它可以在编译时使用。但是 - "five_squared" 在编译时将无法使用。你仍然需要指示它是 "constexpr" (*)。

对于 lambda,情况基本相同。lambda 是 on-the-spot-defined 类的实例,具有 operator()。如果您不自己使其成为 "constexpr" 变量,则不能使 "squared" 成为 "constexpr" 变量。


(*) - 请注意,由于 C++ 语言中的一个特殊规则,使用常量表达式初始化的 "const" 整数自动成为 "constexpr",因此您可以只写 "const auto" 并隐式地获得 "constexpr"。然而,这是一个棘手的特殊情况需要记住,因此如果想将变量设为 "constexpr",我建议您明确指出。感谢 @cigien 指出这一点。


现在我们有了 constexpr,带整数的异常最令人困惑... - Jarod42
@Jarod42 的确如此,但我认为没有办法解决它的问题。 :( - cigien
相反地:因为它晦涩难记,我认为人们根本不应该将其作为假设来使用。 - einpoklum

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接