The ISO C++ standards committee met on April 15-20, 2007 in Oxford, UK. Despite unseasonably sunny and warm weather and good European beer (the best I tried was Budweiser, and no, I’m not kidding because it’s not the American one), we made good progress toward our goal of having a complete draft of C++09 out for public review this year.
(Aside: I delayed posting this article until the post-meeting mailing was online on the ISO C++ website, so that I could add live public links to the referenced documents, for your viewing pleasure.)
New Language Features Voted Into (Draft) C++09
The following new features progressed to the point of being voted into the draft standard at this meeting. I’ve included a link to the final paper number so that you can read up on the gory details of your favorite proposal. (Note that I’m not mentioning changes that are smaller or are just reformulations that have no effect on the semantics of your code, such as that we replaced the wording about sequence points in the standard while maintaining the same effect.)
Template aliases (aka typedef templates, generalized typedefs) [N2258]
This proposal was coauthored by Gabriel Dos Reis and Bjarne Stroustrup. I’ve written before (here in an article and here in a committee proposal) about why you might want to be able to write a typedef that nails down some, but not all, template parameters. The example from the first article is:
// Not legal C++, but it would be nice…
//
template<typename T>
typedef std::map<std::string, T> Registry;// If only we could do the above, we could then write things like:
//
Registry<Employee> employeeRoster;
Registry<void (*)(int)> callbacks;
Registry<ClassFactory*> factories;
What C++09 actually added was not only the equivalent of typedef templates, but something more general. Template aliases allow you to get the same effect as the above using the following syntax:
// Legal in C++00
//
template<typename T>
using Registry = std::map<std::string, T>;// Now these all work as intended
//
Registry<Employee> employeeRoster;
Registry<void (*)(int)> callbacks;
Registry<ClassFactory*> factories;
An example from the second article is motivated by making policy-based-designed templates more usable. Referring to one form of Andrei’s SmartPtr template, I showed that we can write the following wrap-the-typedef-in-a-struct workaround today:
// Today’s workaround
//
template<typename T>
struct shared_ptr {
typedef Loki::SmartPtr<
T, // note that T still varies, but everything else is fixed
RefCounted, NoChecking, false, PointsToOneObject, SingleThreaded, SimplePointer<T>
>
type;
};shared_ptr<int>::type p; // sample usage, “::Type” is ugly
One of the primary reasons (but not the only one) why policy-based smart pointers didn’t make it into C++09 was usability: Although Loki::SmartPtr can express shared_ptr easily as just one of its configurations, the user has to type lots of weird stuff for the policy parameters that is hard to completely hide behind a simple typedef, and so the user would be less inclined to use the feature:
shared_ptr<int>::type p; // the best usability we could provide for a policy-based Shared Ptr
shared_ptr<int> p; // what actually won and is now in C++09
Too bad we didn’t have template aliases then, because now we could have our cake and eat it too:
// Legal in C++09
//
template<typename T>
using shared_ptr =
Loki::SmartPtr<
T,
RefCounted, NoChecking, false, PointsToOneObject, SingleThreaded, SimplePointer<T>
>;
shared_ptr<int> p; // using the alias lets us have a completely natural syntax
This aliasing feature extends beyond templates and is also essentially a generalized replacement for typedef. For example:
// Legal C++98 and C++09
//
typedef int Size;
typedef void (*handler_t)( int );// Legal C++09
//
using Size = int;
using handler_t = void (*)( int );
Especially for such function pointer types, the new form of "using" is simpler than typedef and lets programmers avoid playing guess-where-the-typedef-name-goes because of the C declaration syntax weirdness, at least in this place.
Variadic templates (aka "type varargs" for templates) [N2242; see N2087 for a more readable description and rationale]
This proposal was coauthored by Doug Gregor, Jaakko Järvi, Jens Maurer, and Jason Merrill.
You know how you can call a function like printf with a variable argument list (C’s good old varargs)? Well, there are times you’d like to do that for template arguments lists, too, and now you can. For example, today the C++09 tuple type needs to be declared with some fixed number of defaulted parameters:
// Drawn from draft C++09, before variadic templates
// (when the best tool we had was to hardcode some defaulted parameters)
//
template<
class T1 = unspecified ,
class T2 = unspecified ,
… ,
class TN = unspecified
> class tuple;template<class T1, class T2, …, class TN>
tuple<V1, V2, …, VN> make_tuple( const T1&, const T2& , …, const TN& );
These declarations gets uglier as N gets bigger. And what if you want more than N types? Sorry, Charlie; the implementer just has to write enough types to cover most use cases, and the actual number in the current wording would be nonportable in practice as every implementer has to make their own choice about how many types will be enough.
With variadic templates, we can write it much more simply and flexibly (and portably, once compilers implement the feature):
// Simplified version using variadic templates
// (now in the latest working draft of C++09; see Library section below)
//
template<class… Types> class tuple;template<class… Types>
tuple<VTypes…> make_tuple( Types&… );
This is simpler to define, works with any number of types, and will work portably no matter how many types you use. What’s not to like?
For another example that summarizes other ways to use the feature with class types, consider this example provided by Jonathan Caves (thanks, Jon!):
// Legal in C++09
template<typename… M
ixins>
class X : public Mixins…{
public:
X( const Mixins&… mixins ) : Mixins(mixins)… { }
};class A { };
class B { };
class C { };X<A, B, C> x;
For the type X<A,B,C>, the compiler will generate something like the following:
class X<A, B, C> : public A, public B, public C {
public:
X( A const& __a, B const& __b, C const& __c ) : A(__a), B(__b), C(__c) { }
};
Unicode characters and strings [N2249]
This proposal was written by Lawrence Crowl, based on the ISO C technical report containing similar non-normative extensions for C.
C++ has essentially airlifted in the unofficial C extensions for char16_t and char32_t, and made them available in the new header <cuchar>. Here are a few basic uses:
char16_t* str16 = u"some 16-bit string value";
char32_t* str32 = U"some 32-bit string value";
C++ did a few small things differently from C. In particular, C++ requires the the encoding be UTF, and C++ is making these types a normative (required) part of its language standard.
New Library Features Voted Into (Draft) C++09
As usual, as we vote in language extensions, the library working group continues systematically updating the standard library to make use of those extensions. In particular, this time the library got support for:
- Variadic templates (see above, including its application to std::tuple)
- Unicode characters (see above)
- Rvalue references (see next)
Rvalue references, aka "move construction/assignment," are a useful way to express that you’re constructing or assigning from an object that will no longer be used for anything else — including, for example, a temporary object — and so you can often get a decent performance boost by simply stealing the guts of the other object instead of making a potentially expensive deep copy. For example, move assignment for a string would simply take over the internal state of the source string using just a few pointer/integer assignments, and not perform any allocations. For more details, see this motivational paper which describes the significant performance and usability advantages of move semantics. Updating the standard library to use move semantics included notably updating the containers, iterators, and algorithms to support moveable types, as well as deprecating auto_ptr (wow!) and replacing it with a unique_ptr that expresses unique ownership semantics. (Previously, the library had already added shared_ptr and weak_ptr to express shared ownership and shared observation semantics, so reference-counted shared pointers are already covered.)
If you’re interested in the standardese details of the new move semantics support in the standard library, you can find details of the updates in the following papers: N1856 (basic concepts, pair, and unique_ptr), N1857 (strings), N1858 (containers), N1859 (iterators), N1860 (algorithms), N1861 (valarray), and N1862 (iostreams).
There were a few other housekeeping updates, but for template metaprogramming aficionados one highlight will be the std::enable_if type trait. Have you ever wanted to write a function template that gets completely ignored for types the template wasn’t designed to be used with (as opposed to accidentally becoming a best match and hiding some other function the user really intended to call)? If you’re a template library writer and haven’t yet seen enable_if, see here for a nice Boosty discussion, and you might get to love it too.
Next Meetings
Here are the next meetings of the ISO C++ standards committee, with links to meeting information. The meetings are public, and if you’re in the area please feel free to drop by.
- July 15-20, 2007: Toronto, Canada
- September 30 – October 6: Kona, Hawaii, USA [N2289]
Note that the latter is the meeting at which we are hoping to vote out the first complete draft of the new C++ standard, and it runs straight through to Saturday afternoon. So let me insert a caveat for those who might be thinking, "oh yeah, that sounds like the meeting I think I’ll pick to attend, and catch some rays, ha ha" — having a standards meeting in Hawaii sounds nice, but it’s not nearly what you might think. If you come and want to participate, expect to be shut in windowless rooms all day, and frequently all evening — you’ll only actually see the local landscape if you fly in early or stay late, not during the meeting. But we’ll appreciate your help proofreading mind-numbing swathes of the standard!
That all looks interesting.
Is it really going to be C++09? (i.e., should the Wikipedia page be renamed? http://en.wikipedia.org/wiki/C++0x )
Can variadic templates be combined with template aliases? That is, can I do this?:
template <typename K, typename V, typename… Others>
using my_map = std::map<K, D, Others…>;
Then use my_map as
my_map<float, float> foo; // Exactly like std::map<float, float>
my_map<int, double, my_int_comparison_operator> bar;
And let me echo the other comments: when will compiler vendors start providing these new features?
struct Registry : std::map<std::string, T>
// Now these all work as intended
//
Registry<Employee> employeeRoster;
Registry<void (*)(int)> callbacks;
Registry<ClassFactory*> factories;
Ok, that a bit more of typing, but it is possible ;)
Best Regards,
Ovanes
A question about the new standard: Have there ever been any thought about adding C++/CLI (.NET) like properties to C++0x? They are incredibly useful and nice to use and the syntax is already worked out in C++/CLI for .NET classes. Wouldn’t it be easy to use the same syntax for native classes as well? Since they are only used in context with their class there shouldn’t even be any colisions in C++/CLI after adding the syntax for native classes as well.
And I have to say that properties are a lot nicer to use than the GetWhatever() SetWhatever() methods all C++ programmers are used to.
On Loki reasons not to get into C++09
First of all, excuse my english and don’t consider this rude just because of a harsh wording, I am not a native speaker.
If the reason for a library (Loki) not getting into the standard is that with the previous standard did not allow a simple use, why not express Loki’s smart pointers in C++09 terms –as that would resolve the problem?