难以理解 C++14 宽松的 constexpr 限制

Trouble understanding C++14 Relaxed constexpr restrictions

我遇到了 std::max 函数的新 C++14 签名:

template< class T > 
const T& max( const T& a, const T& b ); // (C++11)

template< class T > 
constexpr const T& max( const T& a, const T& b );// (C++14)

我读过有关 放松 constexpr 限制 的 C++14 提案,但我仍然不明白为什么这个函数 return 值可以 constexpr

示例:

std::vector<int> a, b;
//This does not compile but as my understadnding of `constexpr` this should
int array[std::max(a.size(), b.size()]; (1)
//This is trivial use that does compile
int array[std::max(1,2)]; (2)

在(1)中调用std::maxconstexpr被忽略?

基本问题与宽松的 constexpr 规则没有直接关系,如果参数是常量表达式,constexpr 函数只是一个常量表达式。在你的第二种情况下:

int array[std::max(1,2)];

这是可行的,因为整数文字确实是常量表达式。

C++11 在这种情况下更具体,5.19 [expr.const] 部分中的 C++11 标准草案列出了子表达式不被视为常量表达式并包含以下内容的情况:

an invocation of a constexpr function with arguments that, when substituted by function invocation substitution (7.1.5), do not produce a constant expression;

在 C++14 中删除了该段,我们有以下例外:

an invocation of a function other than a constexpr constructor for a literal class, a constexpr function, or an implicit invocation of a trivial destructor (12.4) [ Note: Overload resolution (13.3) is applied as usual —end note ];

并且我们必须使用关于参数的其余规则(子表达式)。

第一种情况:

int array[std::max(a.size(), b.size()];

std::vector::size 未标记为 constexpr,因此它属于上述例外情况。

另请注意,在 7.1.5 [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 a call to a constexpr function can appear in a constant expression.

将不是常量表达式的参数传递给 constexpr 函数仅意味着该表达式不可用于需要常量表达式的上下文。

正如 dyp 指出的那样 std::max 在 C++11 中没有被定义为 constexpr 由于 各种问题可能包括委员会保守和时间有限,我们可以看到一些涉及的问题在 N3039. it being forgotten see N3856 中说:

This short paper proposes to make the standard functions min and max constexpr. They were top on the list of motivating cases for al- lowing reference parameters for constexpr functions in C++11. They were forgotten after the core language change was accepted

作为参考,我们知道 125.19 节中的常量表达式,它表示:

A literal constant expression is a prvalue core constant expression of literal type, but not pointer type. An integral constant expression is a literal constant expression of integral or unscoped enumeration type. [...]