简体   繁体   English

如果结构化绑定不能是constexpr,为什么它们可以在constexpr函数中使用?

[英]If structured bindings cannot be constexpr why can they be used in constexpr function?

According to this answer apparently there is no good reason why structured bindings are not allowed to be constexpr, yet the standard still forbids it. 根据这个答案,显然没有充分的理由说明为什么不允许结构化绑定是constexpr,但标准仍然禁止它。 In this case, however, shouldn't the use of the structured bindings inside the constexpr function also be prohibited? 但是,在这种情况下,是否应该禁止在constexpr函数中使用结构化绑定? Consider a simple snippet: 考虑一个简单的片段:

#include <utility>

constexpr int foo(std::pair<int, int> p) {
    auto [a, b] = p;
    return a;
}

int main() {
    constexpr int a = foo({1, 2});
    static_assert(a == 1);
}

Both gcc and clang does not cause trouble compiling the code. gccclang都不会在编译代码时造成麻烦。 Is the code ill-formed either way or is this one actually allowed? 代码是否格式不正确或实际允许这个?

In the case of function declaration, the constexpr specifier is an assertion made to the compiler that the function being declared may be evaluated in a constant expression , ie an expression that can be evaluated at compile-time. 在函数声明的情况下, constexpr说明符是对编译器的断言,声明的函数可以在常量表达式中计算 ,即可以在编译时计算的表达式。 Nevertheless the object initialization inside a declaration does not need to have constexpr inside its declaration specifier to be a constant expression . 然而,声明中的对象初始化不需要在其声明说明符中包含constexpr作为常量表达式

Shorter: constexpr function may imply constant expression but constant expression initialization does not need that the associated declaration has a constexpr specifier. 更短: constexpr函数可能意味着常量表达式,常量表达式初始化不需要关联的声明具有constexpr说明符。

You can check this in the C++ standard [dcl.constexpr]: 您可以在C ++标准[dcl.constexpr]中进行检查:

A call to a constexpr function produces the same result as a call to an equivalent non-constexpr function in all respects except that 对constexpr函数的调用产生与在所有方面调用等效的非constexpr函数相同的结果,除了

— a call to a constexpr function can appear in a constant expression[...] - 对constexpr函数的调用可以出现在常量表达式中[...]

This is the evaluation of an expression that determines if an expression is a constant expression [expr.const]: 这是对表达式的求值 ,该表达式确定表达式是否为常量表达式[expr.const]:

An expression e is a core constant expression unless the evaluation of e [...] would evaluate one of the following expression [...] 表达式e是一个核心常量表达式除非e评价 [...]将评估下面的表达式中的一个[...]

A declaration is not an expression , so an initialization of an object being declared is a constant expression irrespective of the presence or not of a constexpr specifier in the declaration. 声明不是表达式 ,因此声明的对象的初始化是一个常量表达式,而不管声明中是否存在constexpr说明符。

Finally, in [dcl.constexpr], it is specified that a constexpr function must be such that there exist parameters for which its body can be evaluated as a constant expression : 最后,在[dcl.constexpr]中,指定constexpr函数必须使得存在可以将其主体作为常量表达式求值的参数:

For a constexpr function or constexpr constructor that is neither defaulted nor a template, if no argument values exist such that an invocation of the function or constructor could be an evaluated subexpression of a core constant expression (8.20), or, for a constructor, a constant initializer for some object (6.6.2), the program is ill-formed, no diagnostic required. 对于既不是默认也不是模板的constexpr函数或constexpr构造函数,如果不存在参数值,则函数或构造函数的调用可以是核心常量表达式的评估子表达式(8.20),或者对于构造函数,某些对象的常量初始化程序(6.6.2),程序格式错误,无需诊断。

When you declare constexpr int a the compiler expects a to be inialized by a constant expression and the expression foo({1,2}) is a constant expression, so your code is well formed. 当你声明constexpr int a ,编译器期望a被一个常量表达式初始化,而表达式foo({1,2})是一个常量表达式,所以你的代码形式很好。

PS: Nevertheless, declaration specifiers (static, thread_local=>static) in the the declaration of function local variable implies that the function cannot be declared constexpr . PS:尽管如此,函数局部变量声明中的声明说明符(static,thread_local => static)意味着函数不能声明为constexpr

There are several requirements that a constexpr function must meet . constexpr函数必须满足几个要求 There are some requirements for the body of a constexpr function, and the shown code does not appear to violate any of them. constexpr函数的主体有一些要求,显示的代码似乎没有违反它们中的任何一个。 The key point is that there is no requirement that every statement in a function must be a constexpr . 关键点在于,不要求函数中的每个语句都必须是constexpr The only interesting requirement in question here, is this one: 这里唯一有趣的要求是这一个:

there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). 存在至少一组参数值,使得函数的调用可以是核心常量表达式的计算子表达式(对于构造函数,在常量初始化器中使用就足够了)(从C ++ 14开始)。 No diagnostic is required for a violation of this bullet. 违反此子弹无需诊断。

Note the last sentence. 注意最后一句。 The compiler may, but is not required to, throw a red flag. 编译器可以(但不是必须)抛出红色标记。

The key requirement is merely that there is some assortment of parameter values to the function that results in a constant result from the function (and the function body meets the listed requirements). 关键要求仅仅是函数中存在一些参数值,这些参数值导致函数的常量结果(并且函数体满足列出的要求)。 For example, the function might use a structured binding conditionally; 例如,函数可以有条件地使用结构化绑定; but for some set of parameter values do something else, producing a constant result. 但是对于某些参数值集做其他事情,产生一个恒定的结果。 This would tick this checkbox for a constexpr function. 这将勾选constexpr函数的此复选框。

But, despite the sophistication of modern C++ compilers, they may not necessarily be capable of reaching this determination in every possible instance, so, in practice, it would be hard to enforce such a requirement, hence the compilers are permitted to just take this for granted. 但是,尽管现代C ++编译器的复杂性,它们可能不一定能够在每个可能的实例中达到这个决心,因此,在实践中,很难强制执行这样的要求,因此允许编译器将其用于理所当然的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么引用上的 constexpr 函数不是 constexpr? - Why is a constexpr function on a reference not constexpr? 为什么函数指针可以是`constexpr`? - Why can function pointers be `constexpr`? constexpr - 函数不能用于常量表达式 - constexpr - function cannot be used in a constant expression constexpr构造函数不能在constexpr构造函数中使用 - constexpr constructor cannot be used in constexpr constructor 使用模板时,Constexpr 函数不是 constexpr - Constexpr function is not constexpr when template is used 在C ++ 14 Standard中,它表示非constexpr函数不能用于constexpr函数的定义吗? - Where in C++14 Standard does it say that a non-constexpr function cannot be used in a definition of a constexpr function? 为什么主要不能成为constexpr? - Why main can not be a constexpr? std::abs 可以在 constexpr 函数中使用,但前提是它是模板化的。 为什么? - std::abs can be used in constexpr function, but only if it's templated. Why? 为什么lambda在转换为函数指针时不能在constexpr上下文中使用? - Why can't lambda, when cast to function pointer, be used in constexpr context? 当 function 只使用类型时,为什么 constexpr 不能用于非常量变量? - Why can't constexpr be used for non-const variables when the function only uses the types?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM