Type long long
In you recall from lesson 2.4 — Integers, the largest integer type C++03 defines is “long”. Long has a platform-specific size that can be either 32 or 64 bits. C++ defines a new type named long long that’s guaranteed to be at least 64 bits in length. Because “long long” was already introduced by C99, many compilers already supported it prior to C++11.
Strangely enough, although C++11 imported long long from C99, they opted not to import fixed-width integers.
Type inference with auto and decltype
My favorite change in C++11 is the introduction of the auto keyword. Consider the common use case where you want to iterate through a vector using a for loop:
for (std::vector<int>::const_iterator itr = myvector.cbegin(); itr != myvector.cend(); ++itr)
Having to determine that the data type for the iterator itr is “std::vector
That’s where the auto keyword comes in:
for (auto itr = myvector.cbegin(); itr != myvector.cend(); ++itr)
The auto keyword tells the compiler to infer the type of the variable from its initializer.
auto x = 5; // x will be type int auto y = 5.5; // y will be type double auto z = y; // z will be type double auto w = "hi"; // w will be type const char*
The decltype can be used to determine the type of an expression at compile-type.
decltype(5) x; // x will be type int because 5 is an int decltype(x) y = 6; // y will be type int because x is an int auto z = x; // z will type type int
Although it may seem like auto and decltype will always deduce the same type, that isn’t the case, as shown by the following example:
const std::vector<int> v(5); // declare a vector v auto a = v[0]; // a will be type int because v[0] is an int decltype(v[0]) b = 1; // b will be type const int&, which is the return type of std::vector<int>::operator[](size_type) const
Generally, if you need a type for a variable you are going to initialize, use auto. decltype is better used when you need the type for something that is not a variable, like a return type.
Type nullptr
In previous iterations of C and C++, 0 acted as both a constant integer and as the null pointer constant, which is why the following oddity occurs:
int *p = 1; // illegal, can't assign an int to an int* variable int *q = 0; // legal, 0 has a special meaning as a null pointer
C++11 defines a new reserved identifier called nullptr (of type nullptr_t) that is not an integer, and can not be converted to an integer (though oddly enough, it can be converted to the boolean value false). 0 remains a valid null point constant for backwards compatibility purposes.
Enum classes
(Note: The following isn’t yet supported by Visual Studio 2010, but it’s simple enough to follow even without trying the examples yourself)
In C++03, enums are not type safe — they are treated as integers even when the enumeration types are distinct. Consider the following case:
#include <iostream>
using namespace std;
int main()
{
enum Color
{
RED,
BLUE
};
enum Fruit
{
BANANA,
APPLE
};
Color a = RED;
Fruit b = BANANA;
if (a == b) // The compiler will compare a and b as integers
cout << "a and b are equal" << endl; // and find they are equal!
else
cout << "a and b are not equal" << endl;
return 0;
}
When C++ compares a and b, it’s comparing them as integers, which means in the above example, a does equal b since they both default to integer 0. This is definitely not as desired since a and b are from different enumerations!
C++11 defines a new concept, the enum class, which makes enums both strongly typed and strongly scoped.
int main()
{
enum class Color
{
RED,
BLUE
};
enum class Fruit
{
BANANA,
APPLE
};
Color a = Color::RED; // note: RED is not accessible any more, we have to use Color::RED
Fruit b = Fruit::BANANA; // note: BANANA is not accessible any more, we have to use Fruit::BANANA
if (a == b) // compile error here, as the compiler doesn't know how to compare different types Color and Fruit
cout << "a and b are equal" << endl;
else
cout << "a and b are not equal" << endl;
return 0;
}
With normal enums, you can access enumerators (eg. RED) directly in the surrounding scope (eg. within main). However, with enum classes, the strong scoping rules mean you have to use a scope qualifier to access the enumerator (eg. Color::RED). This helps keep name pollution and the potential for name conflicts down.
The strong typing rules means that C++ will look for an explicitly defined comparison function to compare Color and Fruit. Since we haven’t defined an operator==(Color, Fruit) function, the compiler won’t understand how to compare a and b in any meaningful way, and this will cause a compile-time error to occur.
B.3 — Range-based for statements and static assert
|
Index
|
B.1 — Introduction to C++11
|
B.3 — Range-based for statements and static assert
Index
B.1 — Introduction to C++11 
[...] B.2 — Long long, auto, decltype, nullptr, and enum classes [...]
[...] B.2 — Long long, auto, decltype, nullptr, and enum classes [...]
C++11 example of enum struct lacks ‘struct’ or ‘class’ after enum:
(right after the sentence ‘C++11 defines a new concept, the enum class, which makes enums both strongly typed and strongly scoped.’)
Should be:
enum struct Color {
RED,
BLUE
};
enum struct Fruit {
BANANA,
APPLE
};
Thank you for noticing. Fixed!
Regarding B.2.
C++11 does have fixed integer types (section 18.4)
#include
I know this is nitpicking but – auto is not new. What is new is the definition of auto.
It actually originally is in C (think carry over from B ?).
As the C FAQ points out about the auto keyword :
“One can imagine stylistic uses such as emphasizing that a variable must be automatic, and supposedly some compilers have used it to force a variable not to be in a register. ”
And I seem to remember reading this years ago too – that that is what the use was (variable not in a register).
Again, nothing major important, so you can consider this nitpicking or trivia or … whatever else.