我在N4140的§5.19/ 2中得到了这个例子:
constexpr int incr(int &n) {
return ++n;
}
据我所知,这不是一个constexpr函数.但是这段代码在俚语和g中编译.见live example.我在这里缺少什么?
在C14中,constexpr函数的规则放松了,文章
N3597: Relaxing constraints on constexpr functions.本文介绍了理论和效果,包括以下(重点是):
As in C++11,the constexpr keyword is used to mark functions which the implementation is required to evaluate during translation,if they are used from a context where a constant expression is required. Any valid C++ code is permitted in constexpr functions,including the creation and modification of local variables,and almost all statements,with the restriction that it must be possible for a constexpr function to be used from within a constant expression. A constant expression may still have side-effects which are local to the evaluation and its result.
和:
A handful of syntactic restrictions on constexpr functions are
retained:
- asm-declarations are not permitted.
- try-blocks and function-try-blocks are not permitted.
- Declarations of variables with static and thread storage duration have some restrictions (see below).
我们可以在N4140第7.1.5节[dcl.constexpr]中找到这个内容:
The definition of a constexpr function shall satisfy the following constraints:
-
it shall not be virtual (10.3);
-
its return type shall be a literal type;
-
each of its parameter types shall be a literal type;
-
its function-body shall be = delete,= default,or a compound-statement that does not contain
最后一个例子显示了如何在constexpr中使用incr:
constexpr int h(int k) {
int x = incr(k); // OK: incr(k) is not required to be a core
// constant expression
return x;
}
constexpr int y = h(1); // OK: initializes y with the value 2
// h(1) is a core constant expression because
// the lifetime of k begins inside h(1)
而涵盖k的寿命的规则从h(1)开始就是:
- modification of an object (5.17,5.2.6,5.3.2) unless it is applied to a non-volatile lvalue of literal type
that refers to a non-volatile object whose lifetime began within the evaluation of e;
7.1.5 [dcl.constexpr]中的措词告诉我们为什么incr是一个有效的constexpr:
For a non-template,non-defaulted constexpr function or a non-template,non-defaulted,non-inheriting
constexpr constructor,if no argument values exist such that an invocation of the function or constructor
could be an evaluated subexpression of a core constant expression (5.19),the program is ill-formed; no
diagnostic required.
作为T.C的修改示例:
constexpr int& as_lvalue(int&& i){ return i; }
constexpr int x = incr(as_lvalue(1)) ;
显示,我们确实可以使用incr作为核心常数表达式的子表达式,因此它不是不成形的.