When should literal classes be used in C++? - c++

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
struct Data {
int i;
int j;
};
Data init_data(); // calculate something
const Data data = init_data();
i.e. when the program starts, before main runs, 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 constexpr constructor and any functions called in the full expression must be constexpr functions.
The type Data is trivial so its implicitly-declared constructors are constexpr constructors, so to make the global data undergo constant initialization we just need to make init_data() be a constexpr function:
struct Data {
int i;
int j;
};
constexpr Data init_data(); // calculate something
constexpr Data data = init_data();
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 data object as a compile-time constant, we can use it in other constant expressions e.g. to initialize other compile-time constants:
const int i = ::data.i;
And we can use the Data type for a static data member with an in-class initializer:
struct MoreData {
static constexpr Data zerozero = Data{}; // OK, Data is a literal type
};
If Data wasn't a literal type we would have to write:
struct MoreData {
static const Data zerozero;
};
// in moredata.cc
const Data MoreData::zerozero = Data{};
And then code which only sees the header doesn't know the value of MoreData::zerozero and 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 1 or 0x23 or 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 a constexpr function) but can still be used as a compile-time constant.
Also I'd want to know if a set member function needs to be constexpr, i.e.
A constexpr member function is a special case of a const member 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 constexpr constructor. That doesn't mean all objects of that type must be constexpr constants, it just means that objects of that type can be constexpr constants if they are declared as such and are initialized using one of the class' constexpr constructors. To use the Data example again, most objects in your program would not be constants:
Data d = { 0, 1 };
d.i = d.i + 5;
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

constexpr fixes a problem in C++98 when using numeric limits. Before C++11 an expression such as
std::numeric_limits<short>::max()
can not be used as integral constant, although it is almost equal to macro INT_MAX. with C++11, such an expression is declared as constexpr so that, for example,
you can use it to declare arrays or in compile-time computations (metaprogramming):
std::array<float,std::numeric_limits<short>::max()> a;

A big advantage of constexpr classes is that they may be put into .ro data which can lead to executable size reductions and performance boosts. Esp. for geometric types e.g. or similar 'simple' types this is very neat as you could also get rid of "magic" numbers. See e.g. https://www.kdab.com/kdab-contributions-to-qt-5-0-part-4/.

Related

Understanding void constexpr-functions in c++14 [duplicate]

Here is what I read: using alias for static member functions?
In the answer I see a suggestion to use constexpr. What is the reason to use constexpr for void functions.
Please demonstrate a simple use case. I am new to constexpr so in complex examples I will not understand the gist.
Rahul's answer cites the standard paragraph which allow void constexpr functions, but it doesn't give a use-case. One use-case that comes to my mind would be to have a constexpr class, and as usual factor out behavior common to method in helper methods. The standard explicitly mentions function doing checks, e.g. assertions. I don't have a concrete example at hand, but I can imagine something like
class A
{
public:
constexpr X doSomething(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
constexpr X doSomethingElse(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
private:
constexpr void constraintOnYArguments(Y arg) {
}
constexpr void checkInvariant() {
// some checks
if (!some condition) {
throw std::logic_error("Oh no!");
}
}
};
As per the C++ 14 standard, void is a literal type
A type is a literal type if it is:
— void; or
— a scalar type; or
— a reference type; or
— an array of literal type; or
— a class type (Clause 9) that has all of the following properties: —
it has a trivial destructor,
— it is an aggregate type (8.5.1) or has at least one constexpr
constructor or constructor template that is not a copy or move
constructor, and
— all of its non-static data members and base classes are of
non-volatile literal types.
From here:
An arbitrary expression-statement is permitted, in order to allow
calls to functions performing checks and to allow assert-like
constructs. void also becomes a literal type, so that constexpr
functions which exist only to perform such checks may return void.
A reasonable use case is the manipulation of volatile variables. The following is a very simplified case from embedded programming using GNU tools (g++, ld):
To make an address of a peripheral a constexpr, you need to put it at a fixed location. This must be done in a linker script:
⋮
/* Define output sections */
SECTIONS
{
GPIO 0x48000000 (NOLOAD) : { *(.GPIO) }
⋮
Now, the .GPIO section is at the fixed address 0x48000400. Peripherals can be modeled by PODs containing volatile members. In the following example, the POD is named gpio_t and has just a single member: mode. The member can be set up in a constexpr function. Of course, there is no benefit to use a function to set a variable to a constant value. But in real use cases values and addresses have to be calculated. Think, e.g., of setting a divider for a Baud rate.
struct gpio_t {
volatile std::uint32_t mode;
};
__attribute__ ((section (".GPIO"))) gpio_t Gpio = {0};
static constexpr gpio_t *port {&Gpio};
static constexpr void init () {
port->mode = 42u;
};
void main {
init ();
⋮
};
Note: The C-style idiom of casting integers to addresses does not work because it reinterpret_cast<> does not qualify for creating constexpr pointers (see Since C++14 illegal). The following fails:
constexpr gpio_t *port {(gpio_t *) 0x48000400};
As long as parameter number is an integral constant, this constexpr version will compute the result at compile-time (C++11 compilers only). And when the number is a run-time integer, this same function is perfectly capable of computing the result at run-time. So you don't need two different versions of the same program: one for compile-time and another for run-time. One implementation does it all.

Any reason to declare constexpr for a function that returns void?

Here is what I read: using alias for static member functions?
In the answer I see a suggestion to use constexpr. What is the reason to use constexpr for void functions.
Please demonstrate a simple use case. I am new to constexpr so in complex examples I will not understand the gist.
Rahul's answer cites the standard paragraph which allow void constexpr functions, but it doesn't give a use-case. One use-case that comes to my mind would be to have a constexpr class, and as usual factor out behavior common to method in helper methods. The standard explicitly mentions function doing checks, e.g. assertions. I don't have a concrete example at hand, but I can imagine something like
class A
{
public:
constexpr X doSomething(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
constexpr X doSomethingElse(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
private:
constexpr void constraintOnYArguments(Y arg) {
}
constexpr void checkInvariant() {
// some checks
if (!some condition) {
throw std::logic_error("Oh no!");
}
}
};
As per the C++ 14 standard, void is a literal type
A type is a literal type if it is:
— void; or
— a scalar type; or
— a reference type; or
— an array of literal type; or
— a class type (Clause 9) that has all of the following properties: —
it has a trivial destructor,
— it is an aggregate type (8.5.1) or has at least one constexpr
constructor or constructor template that is not a copy or move
constructor, and
— all of its non-static data members and base classes are of
non-volatile literal types.
From here:
An arbitrary expression-statement is permitted, in order to allow
calls to functions performing checks and to allow assert-like
constructs. void also becomes a literal type, so that constexpr
functions which exist only to perform such checks may return void.
A reasonable use case is the manipulation of volatile variables. The following is a very simplified case from embedded programming using GNU tools (g++, ld):
To make an address of a peripheral a constexpr, you need to put it at a fixed location. This must be done in a linker script:
⋮
/* Define output sections */
SECTIONS
{
GPIO 0x48000000 (NOLOAD) : { *(.GPIO) }
⋮
Now, the .GPIO section is at the fixed address 0x48000400. Peripherals can be modeled by PODs containing volatile members. In the following example, the POD is named gpio_t and has just a single member: mode. The member can be set up in a constexpr function. Of course, there is no benefit to use a function to set a variable to a constant value. But in real use cases values and addresses have to be calculated. Think, e.g., of setting a divider for a Baud rate.
struct gpio_t {
volatile std::uint32_t mode;
};
__attribute__ ((section (".GPIO"))) gpio_t Gpio = {0};
static constexpr gpio_t *port {&Gpio};
static constexpr void init () {
port->mode = 42u;
};
void main {
init ();
⋮
};
Note: The C-style idiom of casting integers to addresses does not work because it reinterpret_cast<> does not qualify for creating constexpr pointers (see Since C++14 illegal). The following fails:
constexpr gpio_t *port {(gpio_t *) 0x48000400};
As long as parameter number is an integral constant, this constexpr version will compute the result at compile-time (C++11 compilers only). And when the number is a run-time integer, this same function is perfectly capable of computing the result at run-time. So you don't need two different versions of the same program: one for compile-time and another for run-time. One implementation does it all.

Does in class member initialization takes place at compile time or run-time?

In C++11 a new feature was introduced where the programmer can initialize class member variables inside class's definition, see code below:
struct foo
{
int size = 3;
int id = 1;
int type = 2;
unsigned char data[3] = {'1', '2', '3'};
};
Is this initialization takes place during compile time or this feature is just syntactic sugar and member variables are initialized in the default constructor?
First of all yes, as stated before, it is syntactic sugar. But since the rules can be too much to remember, here's a logical experiment to help you figure out what happens in compile time and what not
You have your c++11 class that features in class initializers
struct foo { int size = 3; };
And another class that will help us with our experiment
template<int N>
struct experiment { enum { val = N }; };
Let our hypothesis H0 be that initialization does happen in compile time, then we could write
foo a;
experiment<a.size> b;
No luck, we fail to compile. One could argue that failure is due to foo::size being non constant so lets try with
struct foo { const int size = 3; }; // constexpr instead of const would fail as well
Again, as gcc informs us
the value of ‘a’ is not usable in a constant expression
experiment b;
or (more clearly) visual studio 2013 tells us
error C2975: 'N' : invalid template argument for 'example', expected compile-time constant expression
So, we have to discard H0 and deduce that initialization does not happen in compile time.
What would it take to happen in compile time
There is an old syntax that does the trick
struct foo { static const int size = 3; };
Now this compiles but beware this is (technically and logically) no longer in class initialization.
I had to lie for a little to make a point, but to expose the whole truth now : Message errors imply that a is the real problem. You see, since you have an instance for an object (Daniel Frey also mentions this) memory (for members) has to be initialized (at runtime). If the member was (const) static, as in the final example, then it's not part of the subobjects of a(ny) class and you can have your initialization at compile time.
In-class initialisers for member-variables are syntactic sugar for writing them in the constructor initialiser list, unless there's an explicit initialiser already there, in which case they are ignored.
In-class initialisers of static const members are for constant literals, a definition is still needed (though without initialiser).
C++ has the "as if"-rule from C, so anything resulting in the prescribed observed behavior is allowed.
Specifically, that means static objects may be initialised at compile-time.
It's just syntactic sugar. Also consider that an instance usually means memory which has to be initialized with the correct values. Just because these values are provided with a different syntax does not change the fact that the memory needs to be initialized - which happens at run-time.
Its essentially syntactic sugar for a user provided constructor which initializes the values. You are providing default values for data members. When you ask whether this happens at compile time or run time, the answer depends on the context its used in.
Hopefully, these examples will help. Try them in http://gcc.godbolt.org and see the dissassembly and compilation errors.
struct S { int size = 3; };
//s's data members are compile time constants
constexpr S s = {};
//r's data members are run time constants
const S r = {};
//rr's data members are run time constants,
//but we don't know the values in this translation unit
extern const S rr;
template <int X> class Foo {};
//Ok, s.size is a compile time expression
Foo<s.size> f;
//Error, r.size is not a compile time expression
Foo<r.size> g;
//Compile time expression, this is same as return 3;
int foo() { return s.size; }
//This also works
constexpr int cfoo() { return s.size; }
//Compiler will optimize this to return 3; because r.size is const.
int bar() { return r.size; }
//Compiler cannot optimize, because we don't know the value of rr.size
//This will have to read the value of rr.size from memory.
int baz() { return rr.size; }
As others have shown, static data members (and global variables, same thing essentially) for primitive types such as ints and floats have some weird rules where they can be const but still be used in compile time contexts as if they were constexpr. This is for backwards compatibility with C and the lack of the constexpr feature in the past. Its unfortunate now because it just makes understanding constexpr and what differentiates run time expressions from compile time expressions more confusing.
Having int size = 3; is exactly equivalent to having int size; and then each constructor that doesn't already have size in its initializer list (including compiler-generated constructors) having size(3) there.
Strictly speaking C++ doesn't have a distinction between "compile-time" and "run-time".

static const double cannot have an in-class initializer. why is it so?

The problem with the following code is static member of type "const double" cannot have an in-class initializer. Why is applicable only for a 'const double'in the following code? Please help me.
class sample{
static const char mc = '?';
static const double md = 2.2;
static const bool mb = true;
};
const char sample::mc;
const double sample::md;
const bool sample::mb;
int main(){
}
The logic implemented by the C++03 language standard is based on the following rationale.
In C++ an initializer is a part of object definition. What you write inside the class for static members is actually only a declaration. So, formally speaking, specifying initializers for any static members directly inside the class is "incorrect". It is contrary to the general declaration/definition concepts of the language. Whatever static data you declare inside the class has to be defined later anyway. That's where you will have your chance to specify the initializers.
An exception from this rule was made for static integer constants, because such constants in C++ can form Integral Constant Expressions (ICEs). ICEs play an important role in the language, and in order for them to work as intended the values of integral constants have to be visible in all translation units. In order to make the value of some constant visible in all translation units, it has to be visible at the point of declaration. To achieve that the language allows specifying the initializer directly in class.
Additionally, on many hardware platforms constant integer operands can be embedded directly into the machine commands. Or the constant can be completely eliminated or replaced (like, for example, multiplication by 8 can be implemented as a shift by 3). In order to facilitate generation of machine code with embedded operands and/or various arithmetical optimizations it is important to have the values of integral constants visible in all translation units.
Non-integral types do not have any functionality similar to ICE. Also, hardware platforms do not normally allow embedding non-integral operands directly into the machine commands. For this reason the above "exception from the rules" does not extend to non-integral types. It would simply achieve nothing.
The compiler offered me to use constexpr instead of const:
static_consts.cpp:3:29: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double sample::md’ of non-integral type [-fpermissive]
static_consts.cpp:7:22: error: ‘constexpr’ needed for in-class initialization of static data member ‘const double sample::md’ of non-integral type [-fpermissive]
I've just accepted the offer:
class sample{
static const char mc = '?';
static constexpr double md = 2.2;
static const bool mb = true;
};
const char sample::mc;
const bool sample::mb;
int main(){
}
And now it compiles just fine (C++11).
Pre-C++11, only const integral types could be directly initialized in the class definition. It's just a restriction imposed by the standard.
With C++11, this no longer applies.

ios_base and static members

Static constants in the ios_base class are initialized when created, which makes sense for constants. Can non-constant static member variables be initialized the same way, or is this concept only allowed for constant static members?
For non-constant static members with gnu compilers must use always define/allocate space separately from it's deceleration in the header? Is it even proper to initialize constant static members this way?
Class members can be created and initialized only for the static const (integral data type, like int, char, double etc.) members in current C++ standard. For non-static member it's not possible. However, in C++0x that facility is introduced.
Edit: For non-const static member, you can do initialization but you have to do the same in .cpp file (for non template classes). e.g.
struct A
{
static const int i = 0; // ok
static int j; // can declare in .cpp file as below
int k = 2; // error, but valid in C++0x
const int l = 3; // error, valid in C++0x
static const int m[2] = {1,2}; // error, should be an integral type
static const string n = "hi"; // error, should be an integral type
};
int A::j = 1 // declare in class body, and define outside
Because static data members must be
explicitly defined in exactly one
compilation unit.
From C++ FAQ
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12
You might want to read the whole "Constructors" section about "static data member" to clearly understand it.
http://www.parashift.com/c++-faq-lite/ctors.html