【发布时间】:2021-02-06 12:38:52
【问题描述】:
为什么用auto 关键字定义变量时不带有用于初始化它的表达式的constexpr'ness?
例如,考虑以下代码:
#include <string_view>
constexpr std::string_view f() { return "hello"; }
static constexpr std::string_view g() {
constexpr auto x = f(); // (*)
return x.substr(1, 3);
}
int foo() { return g().length(); }
使用 GCC 10.2 和 --std=c++20 -fsanitize=undefined -O3,此 compiles 变为:
foo():
mov eax, 3
ret
但是如果我们删除第 (*) 行的 constexpr,我们将得到一个 27 行的程序,其中包含一堆指针、一个长字符串常量等。
注意事项:
- 我将此问题标记为 C++20,但我没有理由相信此行为与 C++11 不同。
- 这个问题不是关于示例的,它是关于
autow.r.t 的一般行为。constexprness。该示例仅表明,如果我们没有明确告知 GCC 不会将 x 视为constexpr。
【问题讨论】:
-
auto的工作方式与模板相同。顶级 const 被忽略。constexpr永远不会被推断出来。 -
constexpr不是类型系统的一部分,它不是可以推断的。 -
constexpr 表达式不会(保证)在编译时超出 constexpr 上下文进行评估。您的示例的效果是由编译器的优化引起的,它可能没有默认的优化级别。检查这个sample。
-
@Barry:但是当您想在 constexpr 上下文中使用表达式时,它是“推导的”。那么为什么不把这个特性和那个类型一起带到 auto 上呢?
-
如果你有
template <typename T> void foo(T)并传递给它const int,T将是int,而不是const int,因为顶级 const 已从推导类型中删除。auto也会发生同样的事情。它删除了const。
标签: c++ type-inference constexpr c++20 auto