本文介绍了混合使用constexpr和const?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我读了一些标准库的CLang实现,它使我对const和constexpr有点困惑。 template< ; class _Tp,_Tp __v> struct integer_constant { static constexpr _Tp value = __v; }; template< class _Tp,_Tp __v> const _Tp integral_constant< _Tp,__v> :: value; 令我困惑的是,它使用constexpr在类定义和const外。我的问题是,是否允许?在什么情况下const和constexpr我可以交换使用?当然constexpr函数不能应用于const,所以我说的是const数据和constexpr数据。 我读了一些标准草案和建议在 http://www.open-std.org/jtc1/sc22/wg21 /docs/papers/2007/n2235.pdf ,,但它让我感觉更混乱。所以我还有一些问题, 在N2235中,它清楚地说明,const数据不能保证是一个编译时常量,见下面的例子, struct S { static const int size; }; const int limit = 2 * S :: size; //动态初始化 const int S :: size = 256; 和constexpr应该解决这个问题,所以至少在这种情况下,constexpr不允许如下, struct S { static const int size; }; constexpr int limit = 2 * S :: size; //应该是我的理解中的错误 const int S :: size = 256;但是,在阅读C ++标准草案N3225之后,我看不到明确说明上面的例子会导致一个错误。错误。特别是,从7.1.5 / 9, 在对象声明中使用的constexpr说明符声明对象 as const。这样的对象应该有字面类型,并且应该初始化。 如果它是由构造函数调用初始化的,构造函数应该是一个 constexpr构造函数,构造函数的每个参数应该是一个常量表达式。该调用是常量表达式(5.19)。 否则,出现在其初始化器中的每个完整表达式都将是一个常量表达式。 因此,如果constexpr int limit = 2 * S :: size;是无效的,那么S :: size不能是常量表达式,那么从5.19(常量表达式),我看不到标准disallow 2 * S :: size在上面的例子中不是常量表达式。 任何人都可以指出我忽略的东西吗?非常感谢。解决方案 S :: size不是一个常量表达式,根据N3225§5.19p2: 条件表达式是一个常量表达式,除非它涉及到以下之一... 一个左值到右值的转换(4.1),除非它应用于 指向非易失性const的整数或枚举类型的glvalue具有先前初始化的对象,用常量表达式初始化,或 [不适用的其他条件] $请注意我所引用的第二个项目符号是如何允许一个整数静态数据成员,该成员本身用一个常量表达式初始化也可以。是一个常量表达式,但你的S :: size是未初始化的。 (注意:常量表达式是用条件表达式定义的,因为C ++语法工作。) 如果你想知道如何进行左值到右值转换,请参阅§5p9: 每当一个glvalue表达式作为一个操作符的操作数出现,该操作符期望该操作数的prvalue值时,左值到右值(4.1),数组到指针(4.2) 这可能是一个很好的例子,说明如何将表达式转换为prvalue。阅读标准不是一个很好的参考,虽然还没有很多其他可用的0x。 I read a little of CLang implementation of standard library and it confuses me a little bit on const and constexpr.template<class _Tp, _Tp __v>struct integral_constant{ static constexpr _Tp value = __v;};template<class _Tp, _Tp __v>const _Tp integral_constant<_Tp, __v>::value;What makes me confusing is that, it is using constexpr inside class definition and const outside. My question is, is that allowed? And under what situation const and constexpr can me be used interchangingly? Of course constexpr functions cannot apply to const, so I am talking about const data and constexpr data.I did read some standard draft and the proposal inhttp://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2235.pdf,but it makes me feel more confusing. So I have some more questions,In N2235, it clearly states that, const data are not guaranteed to be a compile time constants, see the following example,struct S {static const int size;};const int limit = 2 * S::size; // dynamic initializationconst int S::size = 256;and constexpr is supposed to solve this, so at least under this situation, constexpr is not allowed as below,struct S {static const int size;};constexpr int limit = 2 * S::size; // shall be error in my understandingconst int S::size = 256;However, after reading C++ standard draft N3225, I see nowhere explicitly stated that the above example shall cause an error. Particularly, from 7.1.5/9, A constexpr specifier used in an object declaration declares the object as const. Such an object shall have literal type and shall be initialized. If it is initialized by a constructor call, the constructor shall be a constexpr constructor and every argument to the constructor shall be a constant expression. that call shall be a constant expression (5.19). Otherwise, every full-expression that appears in its initializer shall be a constant expression.Therefore, if constexpr int limit = 2 * S::size; is invalid, then S::size must not be an constant expression, then from 5.19 (constant expression), I see nowhere the standard disallow 2 * S::size in the above example to not be a constant expression.Can anybody point out anything I have overlooked? Thank you very much. 解决方案 S::size is not a constant expression according to N3225 §5.19p2: A conditional-expression is a constant expression unless it involves one of the following… an lvalue-to-rvalue conversion (4.1) unless it is applied to a glvalue of integral or enumeration type that refers to a non-volatile const object with a preceding initialization, initialized with a constant expression, or [other conditions that don't apply]Note how the second bullet point I quoted allows an integral static data member which is itself initialized with a constant expression to also be a constant expression, but your S::size is uninitialized.(Side-note: constant-expressions are defined in terms of conditional-expressions because that's how the C++ grammar works.)If you're wondering how the lvalue-to-rvalue conversion happens, see §5p9: Whenever a glvalue expression appears as an operand of an operator that expects a prvalue for that operand, the lvalue-to-rvalue (4.1), array-to-pointer (4.2), or function-to-pointer (4.3) standard conversions are applied to convert the expression to a prvalue.This is probably a good example of how reading the standard doesn't make a good reference, though there's not much else available yet for 0x. 这篇关于混合使用constexpr和const?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-22 17:34