Archive
Introduction to C++0x
I’ve just recorded a short video introducing you to C++0x. Unless you’ve been living under a rock for the past few years, or don’t have an internet connection (and somehow still frequent my blog) then chances are you know about it anyway. You may well have been reading Dr. Stroustrup’s FAQ, my own C++0x articles, or some of the many other sources available on the new standard.
Anyway, this video is going to be the first in a series that will cover C++0x features in video form, rather than textual. Enjoy!
Two Small C++0x Features
I’m going to mention two little C++0x features today. I don’t have much time, but I thought I may as well share them briefly. They’re both fairly small and quick to explain, so let’s get to it. I’ve put the one that’s faster to discuss first. As always, check out Dr. Stroustrup’s FAQ for more information.
I. long long Integers
The C++0x standard has a new type – the long long integer – which is guaranteed to be at least 64bit. No more annoyances because too many compilers make int and long int the same size – use long long int and you can be sure that you’ll get 8 whole bytes of integral goodness!
Apparently this feature was already supported by a number of compilers, but it’s standard now so you don’t have to worry about non portable code (well you do, but you can blame compiler vendors for being slow to comply with the new standard…
). There’s really not much to say here, merely that you have two 64bit types: long long (i.e. long long int) and unsigned long long (i.e. unsigned long long int). Also note the new literal suffixes: LL for long long and ULL for unsigned long long.
II. nullptr
This one’s exactly as the name suggests: that is, the nullptr keyword represents a null pointer. Previously one might have done something like this:
char* name = 0;
In C++0x, however, one can do the following instead:
char* name2 = nullptr;
These two examples have the same result, that is name == name2 would evaluate to true. On the other hand, while we can also assign the value o to an integral type, we can assign nullptr only to a pointer variable. So the following would yield a compiler error:
int age = nullptr; // compiler error: age is not a pointer
This is all well and good, but it’s quicker to type 0 than nullptr. Why, therefore, should we use the latter over the former? Well the fact is that the double meaning of 0 as the integer 0 and as the null pointer 0×00000000 has the potential to cause problems. Allow me to demonstrate using Dr. Stroustrup’s example. Consider a function f with two overloads:
- void f(int)
- void f(char*)
We call f(0). What happens? Well in fact, f(int) is called, but what if we wanted to pass a null pointer to f(char*). Previously we should have had to resort to something like f((char*)0), which is rather undesirable, in my opinion at least (and, presumably in the opinion of committee members!). So, do the right thing and use nullptr to represent your null pointers.
C++ Renaissance: The “Going Native” Channel
Check out this post on Herb Sutter’s blog: it provides links to a new series of videos on MSDN all about native coding, particularly in C++. Enjoy!
More on Suffix Return Types
Previously I discusses suffix return types, and I provided an example of how it could simplify notation. This:
Icanos::System::String Icanos::System::FormattedLog::ApplyIndent(const String&);
became this, which I’m sure you’ll agree is tidier:
auto Icanos::System::FormattedLog::ApplyIndent(const String&) -> String;
However, there is another application which is perhaps more relevant. The above example is a matter of scope: String is not in scope before the function’s name, but it is after, so we don’t have to qualify it fully. But the following is also to do with scope.
Consider a C++ template function to find the quotient of two values (yes, I know it’s contrived…). It’s return type depends on the template types passed to it. Indeed, it’s return type is decltype(s / t) where s and t are the values to be divided. But we can’t put this as s and t aren’t in scope before the parameter list. They are, however, in scope after it.
template <class S, class T>
auto quotient(S s, T t) -> decltype(s / t)
{
return s/t;
}
And there we are. It works beautifully! Just as a contrast, here is how Dr. Stroustrup says you would have to do it with C++03/98 syntax. As he points out, it is much more messy.
template <class S, class T>
declytype(*(S*)(0) / *(T*)(0)) quotient(S s, T t)
{
return s/t;
}
While s and t aren’t in scope before the parameter list, S and T (the types themselves) are in scope. Thus we can cast 0 to a null pointer to S and a null pointer to T, and then dereference it. This wouldn’t be acceptable at runtime, but it works as decltype is evaluated at compile time. Though it works, the former solution is clearly nicer.
Read more about it on his FAQ.
C++0x Declared Types
Sometimes you might want to know the type of an expression. At runtime you can use RTTI (runtime type information) and typeid. But what about compile time? You can use typeof in some cases, but that is a nonstandard extension. C++0x provides a new keyword decltype which adds this functionality to the standard.
decltype stands for declared type and you can read more about it on Dr. Stroustrup’s FAQ. In summary though, if e is an expression, declytype(e) represents the type of the expression. So decltype(4) would mean int and decltype(4.0f) would mean float. Naturally this can be extended to user types.
Note that decltype is supported by Microsoft Visual C++, Intel Composer XE and GCC/MinGW.
class Blog {
// etc
};
Blog SFMLCoder;
decltype(SFMLCoder) // <--- this means 'Blog'
Read on for examples! Read more…
C++0x Suffix Return Types
Time for another little C++0x feature. Like auto, it is supported by Microsoft Visual C++ 2010 and MinGW. If you have a different compiler, then you can’t go wrong by trying it anyway. Just remember that if you get compiler errors, it could mean the feature isn’t supported by your compiler.
Let’s get straight to it with an example. Consider the following example of how we would normally code a function:
bool Init()
{
// etc
return true;
}
And here is the way using trailing return types:
auto Init() -> bool
{
// etc
return true;
}
Why would we want to do this? It’s more work after all. Well yes, it is more work in this case, but now consider a real world example. In my game engine’s log, I have a function which takes a string, applies some formatting to it and returns it. The string type is a typedef‘d std::string called String in the Icanos::System namespace.
This is how I had written the function before I took advantage of this C++0x feature.
Icanos::System::String Icanos::System::FormattedLog::ApplyIndent(const String& message, const String& source)
{
// etc
}
I have to qualify the String return type in full. But if I could put the return type after, the String type would already be in scope as we’ve qualified the function’s scope, thus simplifying notation.
auto Icanos::System::FormattedLog::ApplyIndent(const String& message, const String& source) -> String
{
// etc
}
After the function name, everything in Icanos::System is already in scope, so we don’t need to qualify the namespaces on String again.
Well I hope you’ve enjoyed my introduction to suffix return types – which you may also see referred to as trailing return types. If you’d like to read more about them, check out Dr. Stroustrup’s FAQ.
Coincidentally, it was originally suggested (as noted in Stroustrup’s FAQ) that suffix return types be signified using [] rather than auto. However, due to controversy, auto is suggested as an alternative. Both MinGW and Microsoft Visual C++ generate a compiler error if [] is used.
Related articles
- The C++0x auto type (sfmlcoder.wordpress.com)
- C++0x in Qt (labs.qt.nokia.com)
C++0x!
If you haven’t yet looked into C++0x, then you really should. While many of the features aren’t of course yet provided by compilers, various vendors seem to have started adding some – I know for a fact that Visual Studio has a fair few. If you want to read about the new standard, Bjarne Stroustrup’s FAQ isn’t a bad starting point.
http://www2.research.att.com/~bs/C++0xFAQ.html
Related articles
- The C++0x auto keyword (sfmlcoder.wordpress.com)
- ISO C++ Committee Approves C++0x Final Draft (developers.slashdot.org)
Beware auto!
So yesterday I shared with you all the joys of the auto keyword. It’s certainly at neat feature, and I know I’ll be using it from time to time.
BUT! There is one point you need to take very seriously with auto, and I can’t put enough stress on this point. Please, please don’t just start using auto to declare all your variables, such as those with obvious types. This is just going to make the code hard to read, and doesn’t really achieve anything. Anyway, auto is longer than int and the same length as char, long, and bool.
My point, is that auto should be used in situations where the type to be used is not easy to write out yourself and not otherwise. As Dr. Stroustrup says on his FAQ, the use of auto is ”obviously most useful when that type is either hard to know exactly or hard to write”. So what does this mean?
Well let’s consider two examples based on those from Stroustrup’s page. Read more…
The C++0x auto keyword
You know the C++ auto keyword? The somewhat pointless one which is the default storage specifier anyway? Well in C++0x, the keyword has been re-purposed and now serves a more useful role!
(Remember, this is a feature of the upcoming standard, so it won’t necessary be widely supported yet. However, I have successfully compiled all the code below – apart from bits specifically designed to create errors – in both MSVC and MinGW.)
Consider the following code. Read more…
