My understanding is that this (nonsensical) code is not valid C++14:
class Point {
public:
constexpr double setX(double newX) { return x = newX; }
private:
double x;
};
I'm trying to figure out what part of the (still officially draft) C++14 Standard disallows it. The restrictions on constexpr functions are listed in 7.1.5/2. (Sorry for the mangled formatting. I can't figure out how to beat markdown into making it look right.)
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
- an asm-definition,
- a goto statement,
- a try-block, or
- a definition of a variable of non-literal type or of static or thread storage duration or for which no initialization is performed.
There's nothing there that prohibits assignments to data members. There is such a prohibition in 5.19/2 (bullet 15) (again with mangled formatting, sorry):
A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the abstract machine (1.9), would evaluate one of the following expressions: [...] 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;
But I don't see how 5.19 applies to 7.1.5. Can somebody clarify?
constexpr functions A constexpr function is one whose return value is computable at compile time when consuming code requires it. Consuming code requires the return value at compile time to initialize a constexpr variable, or to provide a non-type template argument.
const can only be used with non-static member functions whereas constexpr can be used with member and non-member functions, even with constructors but with condition that argument and return type must be of literal types.
A template metaprogram runs at compile, but a constexpr function can run at compile time or runtime. Arguments of a template metaprogram can be types, non-types such as int , or templates. There is no state at compile time and, therefore, no modification.
Absolutely not. Not even close. Apart from the fact your macro is an int and your constexpr unsigned is an unsigned , there are important differences and macros only have one advantage.
It is valid C++14. You can modify members of a literal class type as long as the lifetime of the object is contained within the evaluation of the constant expression.
The use of Point
in a constant expression is controversial (CWG DR 1452), but it is allowed by current implementations. It would be a literal class except that it is not aggregate (§3.9.1/10) because it has a private field (§8.5.1/1). However its construction does not invoke its non-constexpr constructor because it is trivially-constructible. Anyway, this issue is fixed by adding a declaration constexpr Point() = default;
.
§5.19 restricts what can be evaluated in a constant expression. One restriction is that only constexpr
functions may be entered. §7.1.5 specifies what functions may be marked constexpr
, but note that constexpr
functions may contain (in a conditional statement) things that cannot be evaluated in a constant expression.
See the proposal papers, second and first drafts.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With