为什么`auto`不采用其初始化表达式的constexpr'性? [英] Why does `auto` not adopt the constexpr'ness of its initializing expression?

查看:102
本文介绍了为什么`auto`不采用其初始化表达式的constexpr'性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么不使用 auto 关键字定义变量时会带有用于初始化它的表达式的 constexpr 'ness?

Why doesn't defining a variable with auto keyword carry the constexpr'ness of the expression used to initialize it?

作为示例,请考虑以下代码:

As an example, consider the following code:

#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 时,此

With GCC 10.2 and --std=c++20 -fsanitize=undefined -O3, this compiles into:

foo():
        mov     eax, 3
        ret

但是,如果我们删除(*)行上的constexpr,我们将获得一个27行的程序,其中包含一堆指针,一个长字符串常量等.

But if we remove the constexpr on line (*), we would get a 27-line program with a bunch of pointers, a long string constant etc.

注意:

  • 我用C ++ 20标记了这个问题,但是我没有理由相信这种行为与C ++ 11的行为不同.
  • 这个问题不是关于示例的 ,而是关于 auto w.r.t的一般行为. constexpr ness.该示例只是表明,如果我们没有明确告知x,则GCC不会将x视为 constexpr .
  • I marked this question C++20, but I have no reason to believe this behavior is different from C++11's.
  • This question is not about the example, it is about the general behavior of auto w.r.t. constexprness. The example simply shows that that GCC does not treat x as constexpr if we don't explicitly tell it to.

推荐答案

auto 用于启用类型推导,而不是您将在此处键入的所有有用内容"的替代. constexpr 不是表达式类型的一部分,因此被 auto 忽略(与 const volatile ,它们是表达式类型的一部分,并可以推导出来.)

auto is intended to enable type deduction, not a replacement for "everything useful you would have typed here". constexpr is not a part of an expression's type, and is thus ignored by auto (as opposed to const and volatile, which are part of an expression's type, and are deduced).

但是,如果我们删除(*)行上的constexpr,我们将得到一个27行的程序,其中包含一堆指针,一个长字符串常量等.

But if we remove the constexpr on line (*), we would get a 27-line program with a bunch of pointers, a long string constant etc.

这是您的编译器的选择.它拥有使该代码消失所需的100%信息.事实并非如此,这并不是C ++标准关注的问题.

That is a choice for your compiler. It has 100% of the information it needs to make that code go away. The fact that it didn't is not the C++ standard's concern.

这是实施质量".问题,而不是标准化问题.如果某个实现在编译时无法按照您的期望运行太多代码,则可以向他们抱怨.

This is a "quality of implementation" issue, not a standardization issue. If an implementation won't run as much of your code at compile-time as you desire, you can complain to them about it.

请记住: constexpr 本身并不是运行时优化.它的意思是允许您编写本来无法写的东西.像 std :: get< g()>(some_tuple)一样.该代码必须在编译时运行,因为它已在模板参数中使用.

Remember: constexpr isn't meant to be a runtime optimization per-se. It's meant to allow you to write things that you otherwise couldn't write. Like std::get<g()>(some_tuple) or whatever. That code has to run at compile-time, since it's being used in a template parameter.

我不是在问某种深度推论,而只是在函数显式为constexpr的情况下问.

I'm not asking about some kind of deep deduction, only about the case of the function explicitly being constexpr.

让我们暂时忘记 auto 用于类型推导,而 constexpr 不是类型系统的一部分.让我们集中讨论如果 auto 仍然可以推断出 constexpr 怎么办.因此,如果< expr> 是一个特定的函数,那么您想要的是 auto 推断 constexpr 指定为 constexpr .

Let's forget for a moment that auto is for type deduction and constexpr is not part of the type system. Let's focus instead on what if auto was supposed to deduce constexpr anyway. So what you want is for auto to only deduce constexpr if <expr> is specifically a function that is designated constexpr.

所以让我们看一些代码:

So let's look at some code:

auto x = constexpr_func();
auto y = constexpr_func() + 5;
auto z = constexpr_func() + constexpr_func();
auto w = constexpr_func_2() + constexpr_func_2();

其中哪些变量是 constexpr ?如果您想要的是我们所拥有的,那么 x 将是 constexpr ,而 y 不会.我个人觉得这既令人惊讶又烦人.

Which of these variables are constexpr? If what you want is what we had, then x would be constexpr, but y would not. I personally would find this both surprising and annoying.

更糟糕的是,如果我们假设 constexpr_func()返回一个 int ,那么 z 也不是 constexpr .但是,如果 constexpr_func_2()返回具有 constexpr运算符+ 的用户定义的文字类型,则将 w constexpr .

Worse, if we assume constexpr_func() returns an int, then z is also not constexpr. But if constexpr_func_2() returns a user-defined literal type that has a constexpr operator+, then w would be constexpr.

这不是很奇怪吗?因此,我强烈怀疑这不是您真正想要的.

Isn't that all very weird? So I highly suspect that this is not what you really want.

您真正想要的是 auto x =< expr> ;; ,如果 constexpr auto x =< expr> ;; 可以推断出 constexpr >将是有效的.

What you really want is for auto x = <expr>; to deduce constexpr if constexpr auto x = <expr>; would be valid.

但实际上,这可以追溯到最初的观点.如果您创建变量 constexpr ,则意味着您希望将其用于某些过程需要 constexpr 的地方.鉴于这一事实,推导 constexpr 没有任何意义,因为您应该需要将其设为 constexpr ,以免出现编译错误.

But really, that goes back to the original point. If you make a variable constexpr, that should mean you want it to be used in a place where being constexpr is required by some process. Given that fact, deducing constexpr makes no sense, because you should need it to be constexpr lest you get a compile error.

这篇关于为什么`auto`不采用其初始化表达式的constexpr'性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆