std :: max()和std :: min()不是constexpr [英] std::max() and std::min() not constexpr

查看:200
本文介绍了std :: max()和std :: min()不是constexpr的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我注意到新标准定义 min(a,b) max(a,b) 没有 constexpr

I just noticed that the new standard defines min(a,b) and max(a,b) without constexpr.

示例来自25.4.7,[alg.min.max ]:

Examples from 25.4.7, [alg.min.max]:

template<class T> const T& min(const T& a, const T& b);
template<class T> T min(initializer_list<T> t);

这不是一个可惜吗?我想要写

Isn't this a pity? I would have liked to write

char data[ max(sizeof(A),sizeof(B)) ];

而不是

char data[ sizeof(A) > sizeof(B) ? sizeof(A) : sizeof(B) ];
char data[ MAX(sizeof(A),sizeof(B)) ]; // using a macro

任何原因为什么这些不能 constexpr

Any reason why those can not be constexpr?

推荐答案

关键更新



下面的分析是错误的,因为它混淆了一件重要的事情。下面的语句我错过了一个重要的细节,这需要一个完全不同的回答。

Critical Update

The below analysis is wrong, because it confuses one important thing. The following statement I did missed one important detail, which requires an entirely different answer.


未命名的引用 / code>返回将引用该操作数。

The unnamed reference max returns will refer to that operand.

这里的问题是 function invocation substitution 完成。如果调用susbstitution将包括对 max 产生的glvalue进行右值转换的左值,一切都会很好,因为从glvalue读取指向临时不是静态存储在常数表达式的计算期间,持续时间很好。但是由于读取发生在函数调用替换之外,函数调用替换的结果是一个左值。规范的相应文本

The problem here is that function invocation substitution is done at that point. If the invocation susbstitution would include the lvalue to rvalue conversion on that glvalue that max yields, everything would be fine, because reading from a glvalue that refers to a temporary not of static storage duration is fine during computation of the constant expression. But since the read happens outside of function invocation substitution, the result of function invocation substitution is an lvalue. The respective text of the spec says


引用常量表达式是一个左值核心常量表达式,指定具有静态存储持续时间或函数的对象。

A reference constant expression is an lvalue core constant expression that designates an object with static storage duration or a function.

但是 max 返回的引用会产生一个左值,未指定的存储持续时间。函数调用替换需要产生一个常量表达式,而不仅仅是一个核心常量表达式。因此 max(sizeof(A),sizeof(B))不能保证工作。

But the reference that max returns yields an lvalue that designates an object of unspecified storage duration. Function invocation substitution is required to yield a constant expression, not merely a core constant expression. So max(sizeof(A), sizeof(B)) is not guaranteed to work.

我无法查看以下(较旧的)文字。看到任何原因,为什么你不想坚持一个 constexpr 那里。无论如何,下面的代码绝对是有用的

I can't see any reason at the moment why you wouldn't want to stick a constexpr there. Anyway, the following code definitely is useful

template<typename T> constexpr
T const& max(T const& a, T const& b) {
  return a > b ? a : b;
}

与其他答案相反,我认为这是合法的。并非所有 max 的实例化都必须是constexpr函数。当前n3242表示

Contrary to what other answers write, I think this is legal. Not all instantiations of max are required to be constexpr functions. The current n3242 says


如果constexpr函数模板或类模板的成员函数的实例化模板特化不能满足一个constexpr函数或constexpr构造函数,该专业化不是一个constexpr函数或constexpr构造函数。

If the instantiated template specialization of a constexpr function template or member function of a class template would fail to satisfy the requirements for a constexpr function or constexpr constructor, that specialization is not a constexpr function or constexpr constructor.

如果你调用模板,产生一个函数模板专门化。调用它将触发函数调用替换。考虑下面的调用

If you call the template, argument deduction will yield a function template specialization. Calling it will trigger function invocation substitution. Consider the following call

int a[max(sizeof(A), sizeof(B))];

它将首先对两个 size_t prvalues到两个引用参数,将两个引用绑定到临时对象来存储它们的值。对于引用临时对象的每个案例,此转换的结果为 glvalue (请参阅4p3)。现在函数调用替换采用这两个glvalues,并用函数体中的 a b / p>

It will first do an implicit conversion of the two size_t prvalues to the two reference parameters, binding both references to temporary objects storing their value. The result of this conversion is a glvalue for each case that refers to a temporary object (see 4p3). Now function invocation substitution takes those two glvalues and substitutes all occurences of a and b in the function body by those glvalues

return (<glval.a>) > (<glval.b>) ? (<glval.a>) : (<glval.b>);

条件将需要在这些glvalue上进行右值转换,这是5.19p2允许的

The condition will require lvalue to rvalue conversions on these glvalues, which are allowed by 5.19p2



  • 一个字面类型的glvalue,指的是用常量表达式初始化的非易失性临时对象

条件表达式将为第一个或第二个操作数生成一个glvalue。未命名的引用 max 返回将引用该操作数。并且在数组维度大小规范中发生的右值转换的最终左值将通过上面引用的相同规则有效。

The conditional expression will yield a glvalue to either the first or second operand. The unnamed reference max returns will refer to that operand. And the final lvalue to rvalue conversion happening in the array dimension size specification will be valid by the same rule quoted above.

请注意, initializer_list 目前没有 constexpr 成员函数。这是一个已知的限制,将处理后C ++ 0x,很可能使那些成员 constexpr

Note that initializer_list currently doesn't have constexpr member functions. This is a known limitation and will be handled post-C++0x, most likely making those members constexpr.

这篇关于std :: max()和std :: min()不是constexpr的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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