Though not necessary, I decided that it was a reasonable idea to validate that C++11 compiling was enabled and that C++11 was supported while generating the make file. This meant adding a try_compile command to the CMake build file for a simple C++11 program. If compiling of the simple program fails, an error is reported and CMake aborts.
The initial simple C++11 program tests two C++11 features. As more C++11 features are used in the project, this simple program will be expanded to test those features also. The two initial features tested are the new universal initializer syntax and the new null pointer. Click Continue... for details of these two features.
I discovered something about CMake syntax, namely else and endif statements no longer require repeating the expression in the if statement (as of CMake 2.6.0). The expression may now be left empty. Repeating the expression can sometimes be misleading, for example:
if (NOT ${SOMETHING})Which makes it seem like the else part is for handling the "not something" condition. Leaving the expression blank, as in else() and endif(), is much less confusing. The rest of the if-else-endif statements in the CMake file will be updated to this style at some point. (This syntax was already used for handling issues with Windows.)
... <not something processing here> ...
else (NOT ${SOMETHING})
... <something procession here> ...
endif (NOT ${SOMETHING})
There was also a statement in the CMake build file that obtained the GCC version for checking, but statements that were checking the version have been since removed, so this statement was also removed. Work is now taking place on a new cpp11 branch.
[branch cpp11 commit 18ed38e9af]
Universal Initializer Syntax
The new universal initializer syntax uses values in braces for initializer values. This is like the standard C initializer for initializing an array:
int a[4] = {1, 2, 3, 4};This type of initializer can now be applied to all variables types:
int i = {1};Also, the equal (=) operator is optional (and it apparently is preferred to leave it out). These initializers can also be used on used to initialize members on a constructor where parentheses were used before:
double d = {2.0};
Class::Class(int i, double d) : m_i {i}, m_d {d} {}This syntax can also be used with the new operator and with constant values:
int *pi = new int{1};An advantage of this syntax is that it prevents narrowing (converting a higher value to a lower value), for example:
func(int{25});
double d = 123.5;This could catch possible programming errors. There are probably a few other places where universal initializers can be used. The new try compile test program tests just a few cases.
int i1 = d; ← this line is accepted (may be an error)
int i2 {d}; ← this line produces a narrowing error
Null Pointer
It was the tradition in C programs to use the definition NULL to represent an unset pointer. This definition is obtained by including stdio.h (and probably a few other standard headers). This definition is defined as zero (when include by a C++ program) or to a void pointer with a value of zero (C program). It was the tradition of C++ programs to just use the zero constant to represent an unset pointer. An actual pointer will never have a zero value.
The problem is that the NULL definition and the zero constant have an integer type (C++), allowing the following statements to be accepted:
int *p1 = 0; ← okay, a null pointerThe new nullptr value that is part of C++11 is an actual unset pointer of any type, but it is not interchangeable as an integer value, therefore:
int *p2 = NULL; ← okay, a null pointer
int i = NULL; ← accepted, but this may be an error
int *p1 {nullptr}; ← any pointer type can be set to nullptrThe new try compile test program tests one case of this.
int i = nullptr; ← error, nullptr is not an integer
No comments:
Post a Comment
All comments and feedback welcomed, whether positive or negative.
(Anonymous comments are allowed, but comments with URL links or unrelated comments will be removed.)