std :: max()和std :: min()不是constexpr

时间:2011-04-09 12:54:00

标签: c++ max c++11 min constexpr

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

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);

这不是很可惜吗?我本来想写的

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

的原因

5 个答案:

答案 0 :(得分:13)

关键更新

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

  

未命名的引用max返回将引用该操作数。

这里的问题是函数调用替换在那时完成。如果调用susbstitution将包括max产生的glvalue上的左值转换的左值,那么一切都会没问题,因为从glvalue中读取一个临时的非静态存储持续时间是很好的常量表达式。但由于读取发生在函数调用替换之外,因此函数调用替换的结果是 lvalue 。规范的相应文本说

  

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

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

考虑到以上因素,需要阅读以下(较旧)的文字


我现在看不出任何理由你不想在那里坚持constexpr。无论如何,以下代码肯定是有用的

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

与其他答案相反,我认为这是合法的。并非max的所有实例都需要constexpr函数。目前的n3242说

  

如果constexpr函数模板的实例化模板特化或类模板的成员函数无法满足constexpr函数或constexpr构造函数的要求,则该特化不是constexpr函数或constexpr构造函数。

如果调用模板,参数推导将产生函数模板特化。调用它将触发函数调用替换。请考虑以下调用

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

它将首先将两个size_t prvalues隐式转换为两个引用参数,将两个引用绑定到存储其值的临时对象。对于引用临时对象的每种情况,此转换的结果是 glvalue (请参阅4p3)。现在,函数调用替换采用这两个glvalues,并用函数体中的ab替换所有glvalues

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

这个条件需要左值来对这些glvalues进行rvalue转换,这是5.19p2允许的

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

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


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

答案 1 :(得分:13)

在C ++ 14中,

std :: min和std :: max are constexpr,这显然意味着没有充分的理由(这些天)没有他们的constexpr。问题解决了: - )

答案 2 :(得分:1)

在C ++ 14中包含constexpr版本的std::min()std::max()表明,制作(版本)这些函数{{1}没有根本障碍}}。当constexpr被添加到C ++ 11时,似乎没有考虑到这一点。

显然,对于提供比较功能的版本,该功能本身必须为constexpr才能使模板扩展成功。

答案 3 :(得分:-1)

如果用常量表达式作为参数调用它们,那么

minmax只是常量表达式。由于它们通常比这更有用,所以你不能发表声明。

这是Wikipedia says about constexpr(强调添加)。我知道维基百科不是最终的参考,但我认为在这种情况下它是正确的。

  

在函数上使用constexpr   对...施加非常严格的限制   该功能可以做什么。首先,   函数必须具有非void返回   类型。二,功能内容   必须是以下形式:return expr。   第三,expr必须是常数   论证后的表达   代换。这种不断表达   可能只调用其他定义的函数   作为constexpr,或者它可能使用其他   常量表达式数据变量。

答案 4 :(得分:-3)

我的猜测是,在一般情况下,运算符&lt;(T,T)也不保证是constexpr。