C++ 2011 bag of features
The now finalized new standard for the C++ language brings a bag of new and exciting features to C++. It will reduce verboseness and increase performance in a lot of areas. Of course, it has to stay backwards compatible; that is why some of the bigger and uglier flaws of C++ can't be changed. Still, it improves the language dramatically. Here is what I will enjoy the most.
Auto and container iterate
Following code annoys me:
std::vector<int> a;
for (std::vector<int>::iterator i = a.begin(); i != a.end(); ++i)
cout << (*i) << endl;
It raises the following question: if I know that a is a vector and I know that a.begin() returns an iterator, why do I have to retell this to the compiler? It knows this as well. Luckily, it is no longer needed:
for (auto i = a.begin(); i != a.end(); ++i)
cout << (*i) << endl;
Nearly a pleasure to read. For even shorter code, I would have used boost::foreach in the past, but this is now also included into the language. And it's syntax is pretty:
for (auto v : a)
cout << v << endl;
This will print all values inside the container a. Since a is a vector of int s, v will be an int as well.
Initializer lists
C++ allows now to initialize even complex types with initializer lists similar to how C did things. This will also replace constructor syntax with brackets for the most parts and it is a good thing, because initializations look more like initializations and not like function calls. The following is valid in C++0x:
std::vector<int> a = { 1, 2, 3, 4, 5 };
You no longer have to mess around with push_back all over the place.
Putting the features together, we can write nice non-verbose code. The following complete C++ program prints the contents of a std::map.
#include <iostream>
#include <map>
using namespace std;
int main(int argc, char const *argv[]) {
map<string,int> cmap {
{"Hello", 5},
{"World", 10}
};
for (auto k : cmap)
cout << k.first << ":" << k.second << endl;
return 0;
}
static_assert and variadic templates
static_assert can be used to write asserts on compile time. Widelands uses this in some places to make sure that space optimization that assume some sizes of datatypes do not break down. In the past, you had to jump through some loops to get this working. Now it is as easy as
static_assert(sizeof(long) == 8, "Your long, it is too small!");
Variadic templates are templates that can take a variable number of arguments. They are used to implement std::tuple for example.
But they can also be used to implement self recursive templates that can consume input one element at a time at compile time. For example the following program does precisely nothing at run-time but converts a binary string to an int at compile time:
template <char... digits> struct _2bin;
template <char high, char... digits> struct _2bin<high, digits...> {
static_assert(high == '0' or high == '1', "no binary number!");
static int const value = (high - '0') * (1 << sizeof...(digits)) +
_2bin<digits...>::value;
};
template <char high> struct _2bin<high> {
static_assert(high == '0' or high == '1', "no binary number!");
static int const value = high - '0';
};
int main(int argc, char const *argv[])
{
const int a = _2bin<'1', '1', '1', '1', '1', '0'>::value;
static_assert(a == 62, "Didn't work out :(");
return 0;
}
Extendable literals
This is still not supported in gcc 4.6, but the standard allows to create an operator for literal suffixes. The following is allowed by the standard but does not compile currently:
template<char... digits> constexpr int operator "" _b() {
return _2bin<digits...>::value;
}
int main(int argc, char const *argv[])
{
const int a = 111110_b;
static_assert(a == 62, "Didn't work out :(");
return 0;
}
Note the constexpr. It tells the compiler that it can evaluate this function on compile time and so it will. The operator "" syntax defines a new literal suffix, _b in this case. It allows to write a literal as seen in the definition of a. Like all operators in C++, this also basically adds syntactic sugar which makes code easier to read.
Extendable literals are a fun to play around with and allow for a lot of domain-specific gravy in C++ code without run-time overhead. Still, it is more of an esoteric new feature of the language. For the specific problem discussed here - binary literals - you are better off using a compiler extension. Most compilers support binary literals in the form of 0b111110 these days.
Conclusion
C++0x brings a bag of nice features. All of the above except for extendable literals are already supported in GCC 4.6, but you need to pass -std=c++0x as argument on the command line while compiling.
If you want to know more, Wikipedia has a detailed rundown of the new features in C++0x. There are some that I did not discuss here and that I am not so exited about as the ones mentioned.
I am looking forward to seeing all those features become more widespread. As far as I am concerned, I will only program C++0x in the future if I have the choice and I will not weep for superseded features that will slowly vanish into oblivion. Altogether, I feel like the standardization committee did a great job with the new standard, it breathes new live into a language that we are stuck with for years or maybe decades to come.