Can someone tell me when are literal classes needed in C++?
I am getting a little confused from constexpr constructors, constexpr members, and I can’t see what the point is. I’d like to see some practical use of it.
Also I’d want to know if a set member function needs to be constexpr, i.e.:
constexpr void set_num(int a) { num = a; }
In C++03 this object has dynamic initialization
i.e. when the program starts, before
mainruns, the function will be called and the object gets initialized.In C++11 the object can have constant initialization, a form of static initialization, meaning that its value is set at compile-time and it’s initialized before the program begins. This is useful to avoid the static initialization order fiasco among other things. To ensure the type gets constant initialization it must be initialized by a constant expression, so must have a
constexprconstructor and any functions called in the full expression must beconstexprfunctions.The type
Datais trivial so its implicitly-declared constructors areconstexprconstructors, so to make the globaldataundergo constant initialization we just need to makeinit_data()be aconstexprfunction:The advantage of a literal type is that such types can be used in other constant expressions i.e. in contexts that require compile-time constants. So now that we have our
dataobject as a compile-time constant, we can use it in other constant expressions e.g. to initialize other compile-time constants:And we can use the
Datatype for a static data member with an in-class initializer:If
Datawasn’t a literal type we would have to write:And then code which only sees the header doesn’t know the value of
MoreData::zerozeroand can’t use it in compile-time optimisations.So the advantage of the “literal type” rules is that they allow you to define new class types that can be used in constant expressions. In C++03 only very few types, such as integers, could be used in constant expressions, e.g. integer literals such as
1or0x23or compile-time constants of integer type. In C++11 you can write you own types which can have moderately complicated logic in their constructors (anything that can be expressed in aconstexprfunction) but can still be used as a compile-time constant.A
constexprmember function is a special case of aconstmember function, so it can’t modify (non-mutable) members of the type. A setter function, which modifies the object, can’t be const.To be a literal type a class must follow some rules including having at least one
constexprconstructor. That doesn’t mean all objects of that type must beconstexprconstants, it just means that objects of that type can beconstexprconstants if they are declared as such and are initialized using one of the class’constexprconstructors. To use theDataexample again, most objects in your program would not be constants:So if you added a setter, a function which modifies the object, then it would only make sense to use it on non-const objects of that type, and like any other functions which modifies the type it should not be