ein*_*ica 0 c++ type-inference constexpr auto c++20
为什么用auto关键字定义变量不带有constexpr用于初始化它的表达式的“性质”?
例如,请考虑以下代码:
#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(); }
Run Code Online (Sandbox Code Playgroud)
使用 GCC 10.2 和--std=c++20 -fsanitize=undefined -O3,编译为:
foo():
mov eax, 3
ret
Run Code Online (Sandbox Code Playgroud)
但是,如果我们删除 (*) 行上的 constexpr,我们将得到一个 27 行的程序,其中包含一堆指针、一个长字符串常量等。
笔记:
autowrt constexprness的一般行为。该示例只是表明 GCC 不会将 x 视为constexpr我们没有明确告诉它。auto旨在启用类型推导,而不是替代“您在此处输入的所有有用内容”。constexpr不是表达式的类型的部件,并因此被忽略auto(相对于const和volatile,这是一个表达式的类型的一部分,并且推导出)。
但是,如果我们删除 (*) 行上的 constexpr,我们将得到一个 27 行的程序,其中包含一堆指针、一个长字符串常量等。
这是您的编译器的选择。它拥有使该代码消失所需的 100% 信息。事实上,它不是 C++ 标准所关心的。
这是一个“实施质量”问题,而不是标准化问题。如果一个实现在编译时没有按照你的意愿运行尽可能多的代码,你可以向他们抱怨。
请记住:constexpr本身并不意味着运行时优化。它的目的是让你写出你无法写的东西。喜欢std::get<g()>(some_tuple)什么的。该代码必须在编译时运行,因为它在模板参数中使用。
我不是在问某种深度推论,只是问函数明确为 constexpr 的情况。
让我们暂时忘记它auto是用于类型推导而constexpr不是类型系统的一部分。让我们转而关注 if无论如何auto应该推断出constexpr的结果。所以,你要什么是auto对唯一的演绎constexpr,如果<expr>是专门被指定的功能constexpr。
那么让我们看一些代码:
auto x = constexpr_func();
auto y = constexpr_func() + 5;
auto z = constexpr_func() + constexpr_func();
auto w = constexpr_func_2() + constexpr_func_2();
Run Code Online (Sandbox Code Playgroud)
这些变量中的哪些是constexpr?如果你想要的是我们所拥有的,那么x将会是constexpr,但y不会。我个人会觉得这既令人惊讶又令人讨厌。
更糟糕的是,如果我们假设constexpr_func()返回一个int,那么z也不是constexpr。但是,如果constexpr_func_2()回报率,有一个用户定义的文本类型constexpr operator+,然后w 会 constexpr。
这一切是不是很奇怪?所以我高度怀疑这不是你真正想要的。
您真正想要的是auto x = <expr>;推断constexpr是否constexpr auto x = <expr>;有效。
但实际上,这又回到了原点。如果你创建了一个变量constexpr,那应该意味着你希望它在constexpr某个过程需要存在的地方使用。鉴于这一事实,推导constexpr毫无意义,因为您应该需要它constexpr以免出现编译错误。