GotW #88: A Candidate For the “Most Important const”

A friend recently asked me whether Example 1 below is legal, and if so what it means. It led to a nice discussion I thought I’d post here. Since it was in close to GotW style already, I thought I’d do another honorary one after all these years… no, I have not made a New Year’s Resolution to resume writing regular GotWs. :-)

JG Questions

Q1: Is the following code legal C++?

// Example 1

string f() { return "abc"; }

void g() {
const string& s = f();
  cout << s << endl;    // can we still use the "temporary" object?
}

A1: Yes.

This is a C++ feature… the code is valid and does exactly what it appears to do.

Normally, a temporary object lasts only until the end of the full expression in which it appears. However, C++ deliberately specifies that binding a temporary object to a reference to const on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself, and thus avoids what would otherwise be a common dangling-reference error. In the example above, the temporary returned by f() lives until the closing curly brace. (Note this only applies to stack-based references. It doesn’t work for references that are members of objects.)

Does this work in practice? Yes, it works on all compilers I tried (except Digital Mars 8.50, so I sent a bug report to Walter to rattle his cage :-) and he quickly fixed it for the Digital Mars 8.51.0 beta).

Q2: What if we take out the const… is Example 2 still legal C++?

// Example 2

string f() { return "abc"; }

void g() {
string& s = f();       // still legal?
  cout << s << endl;
}

A2: No.

The "const" is important. The first line is an error and the code won’t compile portably with this reference to non-const, because f() returns a temporary object (i.e., rvalue) and only lvalues can be bound to references to non-const.

Note: Visual C++ does allow Example 2 but emits a "nonstandard extension used" warning by default. A conforming C++ compiler can always allow otherwise-illegal C++ code to compile and give it some meaning — hey, it could choose to allow inline COBOL if some kooky compiler writer was willing to implement that extension, maybe after a few too many Tequilas. For some kinds of extensions the C++ standard requires that the compiler at least emit some diagnostic to say that the code isn’t valid ISO C++, as this compiler does.

I once heard Andrei Alexandrescu give a talk on ScopeGuard (invented by Petru Marginean) where he used this C++ feature and called it "the most important const I ever wrote." And this brings us to the Guru Question, which highlights the additional subtlety that Andrei’s code deftly leveraged…

Guru Question

Q3: When the reference goes out of scope, which destructor gets called?

A3: The same destructor that would be called for the temporary object. It’s just being delayed.

Corollary: You can take a const Base& to a Derived temporary and it will be destroyed without virtual dispatch on the destructor call.

This is nifty. Consider the following code:

// Example 3

Derived factory(); // construct a Derived object

void g() {
  const Base& b = factory(); // calls Derived::Derived here
  // … use b …
} // calls Derived::~Derived directly here — not Base::~Base + virtual dispatch!

Does this work in practice on real compilers? Yes: Every compiler I have access to calls the correct Derived destructor, including even ancient Borland 5.5 and Visual C++ 6.0 (and Digital Mars, though DM calls the destructor at the wrong time, as noted above).

Andrei leverages this subtlety (of course) in his ScopeGuard implementation to avoid making the implementation classes’ destructors virtual at all, which is okay in that case because those classes otherwise have no need for one.

Updates:

  • 08.01.02 to emphasize the feature applies to stack-based references, and mention Walter’s fix for DM.
  • 08.02.05 to clarify Petru Marginean invented ScopeGuard.

Let’s Be Thoughtful Out There

I knew Hanlon’s Razor: "Never attribute to malice that which can be adequately explained by stupidity." And the variants attributed to Heinlein, described on the same page as adding "… but don’t rule out malice." or "… but keep your eyes open."

But I only just now came across Grey’s Law, which follows the flavor of Clarke’s Third Law: "Any sufficiently advanced incompetence is indistinguishable from malice."

One example that irritates me too is focus-stealing popups. Grr, no, I didn’t mean that enter key to select "Reboot", I was just finishing a paragraph or writing a space. Please, Mr. Callous Software Developer, just leave me alone! I don’t care how important you think your application is — it’s never important enough to pop up on top without warning. No. Bad developer. Down. I said down. Stay.

As a counterexample, I really like how Windows handles the "are you sure you want to run this application?" dialog. Not only does it not steal focus… even better, it ignores the first mouse click when it gets focus. That’s right, if the window is visible but not active, and you click on the "Run" button, it doesn’t also push Run — it merely makes the window active. Then if you hit Run again, it runs. Yes! Good developer!

To paraphrase Hill Street Blues: Let’s be thoughtful out there.

TR1 in (Free) VC++ Express

A few weeks ago I blogged about the VC++ update we plan to ship in the first half of next year, which includes extensive additions to MFC as well as TR1. TR1 is the first set of library extensions published by the C++ committee, nearly all of which have also been adopted into the next C++ standard, C++0x. The update will be available to users of Visual Studio 2008 Standard and above in the first half of 2008… but it will not be immediately available to users of our free C++ compiler, Visual C++ Express.

In response to that announcement, an anonymous commenter asked:

Is there planned support later on for TR1 in the Express edition?

Answer: Yes.

The current goal is to include the MFC Update & TR1 bits in the first service pack to Visual Studio 2008, including the Express Edition, but the final decision on this packaging and the timing of SP1 haven’t been firmed up yet. When they are, I’ll mention it here.

Visual C++ Announcements in Barcelona: TR1 and MFC

Note: Many of you who read this blog aren’t Windows developers. I think you might still be interested in skimming this announcement, because I think it matters to the cross-platform and global C++ community when major vendors are clearly still investing heavily in C++ and C++-based technologies, despite what some naysayers proclaim.

How much does Microsoft care about C++ and non-.NET code? In August, I already blogged about

Now I’m happy to elaborate beyond just hinting, in the wake of announcements made yesterday by our Developer Division VP Soma and by our Visual C++ team. Here’s the scoop.

This month: Visual Studio 2008 ("Orcas") ships

First the comparatively minor news: We have a ship date. By the end of this month, we will ship Visual Studio 2008 ("Orcas"), including Visual C++ 2008 in particular which includes a number of cool features I’ve blogged about before, such as /MP for parallel builds on multicore machines.

But VC++ isn’t stopping there. Instead of waiting another year or two between releases, we’re immediately doing another one, gratis to VC++ 2008 customers:

First half of 2008: VS2008 Update ships

In the first half of 2008, VC++ is additionally going to ship an "expansion pack"-like update that will be available to all owners of Visual Studio 2008 Standard and above. This includes two major pieces that I know will be welcome in two major developer communities.

TR1

"TR1" is the first set of library extensions published by the C++ committee, nearly all of which have also been adopted into the next C++ standard, C++0x. Now that we know what parts seem to be sealed for inclusion in the next C++ standard and stable, we can start shipping them.

The VC++ 2008 update will include a complete implementation of all parts of TR1 that were voted into C++0x, except only for the section on functions added for compatibility with the C99 standard. The update will include features like:

  • smart pointers (e.g., shared_ptr<T>, weak_ptr<T>)
  • regular expression parsing
  • new containers (e.g., tuple, the fixed-size array<T,N>, hash-based containers like unordered_set<T>)
  • sophisticated random number generators
  • polymorphic function wrappers (e.g., function<bool(int)> and bind)
  • type traits

and a bunch more of all that good stuff lurking inside ISO C++ Library TR1. C++0x may tweak some of the interfaces, and we’ll track that as they do. In the meantime, here they are right in VC++.

A huge update to MFC

I hinted about a "huge update to MFC" back in August. Here’s the scoop…

Using this update to MFC, developers will be able to create applications with the “look and feel” of Microsoft’s own UIs:

  • Vista theme support, allowing your application to dynamically switch between themes.
  • The Office 2007 UI, including the Ribbon bar look in all its glory, with the ribbon itself, the pearl, quick access toolbar, status bar, and more.
  • The Office 2003 and XP UI, including Outlook-style shortcut bar, Office-style toolbars and menus, print preview, live font picker, color picker, etc.
  • The Internet Explorer UI, including rebars and task panes in all their glory.
  • The Visual Studio UI, with sophisticated docking functionality, auto hide windows, property grids, MDI tabs, tab groups, and more.

All in native C++ code. In MFC.

Oh, and there are also more things… for example, you can also enable your users to customize your application "on the fly" through live drag and drop of menu items and toolbar buttons; use the new Windows shell management classes to enumerate folders, drives and items, browse for folders, and more; and take advantage of many more new controls you can use right out of the box.

Want a quick tour? Get your quick overview with lots of screen shots in our own Pat Brenner’s VCblog entry, and also check out this handy Channel 9 video interview with Pat.

Implementation notes

Where did we get the code? This time, we decided to buy rather than build. The code for Office 2007 look-and-feel and other items were based on code we got from BCGSoft rather than code we developed internally.

Some people wondered about this, but it’s just an implementation detail. In particular, here are two questions I’ve seen people ask, and my personal answers (I am not speaking for Microsoft):

Q: Does it matter that this is code originally written by another company (BCGSoft)?

A: No. This update is a Microsoft Visual Studio product, full stop. With the full level of testing and support that implies, today and tomorrow.

Like most software companies, Microsoft routinely both builds its own code and integrates licensed software. We’ve long done the latter for the C++ standard library implementation (from Dinkumware), the Office proofing tools and spelling/grammar/thesaurus/hyphenation/etc. dictionaries, and mapping data for Live, to name just a few off the top.

Q: Does it matter that this isn’t the code the Office team used to implement their own look-and-feel? Why didn’t Microsoft ship Office’s own internal code?

A: No, and because we usually don’t because internal code isn’t at the level required of a product, respectively. I wonder if people realize this is the norm, not the exception, so let me explain a little.

Think of Office as the biggest Windows ISV (independent software vendor) that operates mostly as a separate company, even though it happens to be a sister division. Office has always driven the development of their own UI advances separately from Windows and Visual Studio. Windows and Visual Studio, in turn, have always tried to follow quickly in adding support for Office’s advances so that the Windows shell and other third-party applications could present the same look-and-feel wherever they wanted to, and those implementations have usually been:

  1. Later, because Office drove the innovation and the platform and tools followed.
  2. Different from Office’s own internal home-brewed versions, because there’s a huge difference between "solid for internal use" and "productized" with all the additional level of documentation and testing and external usability that requires.

The fact that we have an internal and an external "real" implementation for the same thing doesn’t matter. We’ve always done it that way, and the "real" implementation is equal and fully supported. (I think it’s funny that some worry that they’re not getting Office’s original internal ‘real’ implementation; the real "real" implementation is the one that’s not just for internal use, almost by definition!) Once a UI innovation gets into the Windows UI and/or especially the Visual Studio toolset, it’s first-class and here to stay.

Finally, I said this a huge update. What does "huge" mean? This update nearly doubles the size of MFC. Now, "nearly do
ubles the size of X" can be a bad thing. In this case, though, it’s a Good Thing… in my opinion, at least.

Beta and release availability

The update is expected to be available in beta form in January 2008, and to ship in the first half of 2008. Enjoy!

Wrapping up

Finally, let me express some well-deserved appreciation for a HUGE amount of hard work invested by the Visual C++ team, and our libraries team in particular, to make this happen and bring it to customers. Those of us who spend a good fraction of our lives on the second floor of Building 41 saw it firsthand, and know how hard everyone on the team has worked to make this happen at high quality. Thanks for that; it’s been quite a year of PM design work, coding and QA milestones, bug bars, and shiprooms.

For those who’ve asked what Visual C++ is planning beyond this month’s release, the above is an additional part of the answer. Far from the last part, however, because as Ale Contenti said in his announcement on VCblog about our plans beyond VC++ 2008:

"This is just the first step in our drive to improve the native development experience.  There’s a lot more that we’re working on, but we hope you enjoy this first milestone."

Stay tuned.

Trip Report: October 2007 ISO C++ Standards Meeting

The ISO C++ committee met in Kona on October 1-6. Here’s a quick summary of what we did, and information about upcoming meetings.

What’s in C++0x, and When?

As I’ve blogged before (most recently here and here), the ISO C++ committee is working on the first major revision to the C++ standard, informally called C++0x, which will include a number of welcome changes and enhancements to the language itself as well as to the standard library.

The committee is determined to finish technical work on this standard in 2009. To that end, we plan to publish a feature-complete draft in September 2008, and then spend the next year fine-tuning it to address public feedback and editorial changes.

Note that this represents essentially a one-year slip from the schedule I blogged about at the beginning of the year. Why the slip? There are a few major features that haven’t yet been "checked in" to the working paper and that are long poles for this release. Here are three notable ones:

  • concepts (a way to write constraints for templates that lets us get way better error messages, overloading, and general template usability)
  • advanced concurrency libraries (e.g., thread pools and reader-writer locks)
  • garbage collection

Probably the biggest thing we did at this meeting was to choose time over scope: We decided that we can’t ship C++0x without concepts, but we can and will ship without some or all of the other two.

Concurrency: This was a pivotal meeting for concurrency. We voted a slew of concurrency extensions into the working draft at this meeting, as they happily all got to the ready point at the same time (see below for details):

  • memory model
  • atomics library
  • basic threads, locks, and condition variables

And we decided to essentially stop there; we still plan to add an asynchronous future<T> type in C++0x, but features like thread pools are being deferred until after this standard.

Garbage collection: For C++0x, we’re not going to add explicit support for garbage collection, and only intend to find ways to remove blocking issues like pointer hiding that make it difficult to add garbage collection in a C++ implementation. In particular, the scope of this feature is expected to be constrained as follows:

  • C++0x will include making some uses of disguised pointers undefined, and providing a small set of functions to exempt specific objects from this restriction and to designate pointer-free regions of memory (where these functions would have trivial implementations in a non-collected conforming implementation).
  • C++0x will not include explicit syntax or functions for garbage collection or related features such as finalization. These could well be considered again after C++0x ships.

What we voted into draft C++0x

Here is a list of the main features we voted into the C++0x working draft at this meeting, with links to the relevant papers to read for more information.

nullptr (N2431)

This is an extension from C++/CLI that allows explicitly writing nullptr to designate a null pointer, instead of using the unfortunately-overloaded literal 0 (including its macro spelling of NULL) which makes it hard to distinguish between an null and a zero integer. The proposal was written by myself and Bjarne.

Explicit conversion operators (N2437 and N2434)

You know how in C++ you can make converting constructors only fire when invoked explicitly?

class C {
public:
  C( int );
explicit C( string );
};

void f( C );

f( 1 ); // ok, implicit conversion from int to C
f( "xyzzy" ); // error, no implicit from string literal to C
f( C("xyzzy") ); // ok, explicit conversion to C

But C++ has two ways to write an implicit conversion — using a one-argument constructor as above to convert "from" some other type, or as a conversion operator "to" some other type as shown below, and we now allow explicit also on this second form:

class C {
public:
  operator int();
explicit operator string(); // <– the new feature
};

void f( int );
void g( string );

C c;
f( c ); // ok, implicit conversion from C to int
g( c ); // error, no implicit from C to string
g( string(c) ); // ok, explicit conversion to C

Now the feature is symmetric, which is cool. See paper N2434 for how this feature is being used within the C++ standard library itself.

Concurrency memory model (N2429)

As I wrote in "The Free Lunch Is Over", chip designers and compiler writers "are under so much pressure to deliver ever-faster CPUs that they’ll risk changing the meaning of your program, and possibly break it, in order to make it run faster." This only gets worse in the presence of multiple cores and processors.

A memory model is probably of the lowest-level treaty between programmers and would-be optimizers, and fundamental for any higher-level concurrency work. Quoting from my memory model paper: "A memory model describes (a) how memory reads and writes may be executed by a processor relative to their program order, and (b) how writes by one processor may become visible to other processors. Both aspects affect the valid optimizations that can be performed by compilers, physical processors, and caches, and therefore a key role of the memory model is to define the tradeoff between programmability (stronger guarantees for programmers) and performance (greater flexibility for reordering program memory operations)."

Atomic types (N2427)

Closely related to the memory model is the feature of atomic types that are safe to use concurrently without locks. In C++0x, they will be spelled "atomic<T>". Here’s a sample of how to use them for correct (yes, correct!) Double-Checked Locking in the implementation of a singleton Widget:

atomic<Widget*> Widget::pInstance = 0;

Widget* Widget::Instance() {
  if( pInstance == 0 ) { // 1: first check
    lock<mutex> hold( mutW ); // 2: acquire lock (crit sec enter)
    if( pInstance == 0 ) { // 3: second check
      pInstance = new Widget(); // 4: create and assign
    }
  } // 5: release lock
  return pInstance; // 6: return pointer
}

Threading library (N2447)

You might have noticed that the above example used a lock<mutex>. Those are now in the draft standard too. C++0x now includes support for threads, various flavors of mutexes and locks, and condition variables, along with s
ome other useful concurrency helpers like an efficient and portable std::call_once.

Some other approved features

  • N2170 "Universal Character Names in Literals"
  • N2442 "Raw and Unicode String Literals; Unified Proposal (Rev. 2)"
  • N2439 "Extending move semantics to *this (revised wording)"
  • N2071 "Iostream manipulators for convenient extraction and insertion of struct tm objects"
  • N2401 "Code Conversion Facets for the Standard C++ Library"
  • N2440 "Abandoning a Process"
  • N2436 "Small Allocator Fix-ups"
  • N2408 "Simple Numeric Access Revision 2"

Next Meetings

Here are the next meetings of the ISO C++ standards committee, with links to meeting information where available.

  • February 24 – March 1, 2008: Bellevue, Washington, USA (N2465)
  • June 8-14, 2008: Sophia Antipolis, France
  • September 14-20, 2008: San Francisco Bay area, California, USA (this is the anticipated date)

The meetings are public, and if you’re in the area please feel free to drop by.

Suggestion for “Required Viewing”: Machine Architecture Talk Online

Over the past 15 years or so that I’ve been giving software development talks, I’ve never had the chutzpah to suggest one of my own talks be considered "required viewing" for serious developers regardless of language or platform. But I’m going to suggest it now.

Two years ago, several highly experienced software architects I know (whose names many of you gentle readers would recognize) complained to me privately that "we shouldn’t let developers labor in ignorance" of how the enormous complexity of modern commodity computers affects our code’s performance and correctness. From that seed and others like it sprang this talk, now freely available online:

Section of a slide imageMachine Architecture: Things Your Programming Language Never Told You (117 minutes)

Video: Google video (recorded live on Sep 19, 2007)
Slides: PDF slides

Abstract: Programmers are routinely surprised at what simple code actually does and how expensive it can be, because so many of us are unaware of the increasing complexity of the machine on which the program actually runs. This talk examines the “real meanings” and “true costs” of the code we write and run especially on commodity and server systems, by delving into the performance effects of bandwidth vs. latency limitations, the ever-deepening memory hierarchy, the changing costs arising from the hardware concurrency explosion, memory model effects all the way from the compiler to the CPU to the chipset to the cache, and more — and what you can do about them.

Teaser: Would you be surprised to discover that only about 1% (one percent) of all the transistors on your modern CPU exist to ever compute anything? And that the other 99% (ninety-nine percent) of your CPU’s transistors are essentially dedicated to nothing but hiding memory latency? Those are round numbers, of course. But you get the idea…

So how do we cope with latency...?This is a talk I wish I’d been able to attend years ago. Consider making this required viewing for your team, including for new hires in software development roles. I guarantee it’ll be time well invested.

Here’s one suggestion: Roll your own training session. Arrange an extended lunch brownbag for your developers in a conference or training room, give each person a printout of the PDF slides to follow along and make notes, and display the video on the big screen. For extra benefit, leave a little time for group discussion, both during the session (the Pause feature is your friend) and afterwards ("how does this apply to our projects?"). Presto, instant training session — and you don’t even have to put your developers on a plane to attend a class somewhere, or arrange for a speaker to fly out to your site.

Finally, if you like the material and agree that it’s worthwhile, please help spread the word. For example, you can tell Slashdot by going to Submit Story. Or, if you prefer, you can tell Digg, or Reddit, or one of the others… you know the rest of the usual suspects.

Enjoy!

Omit Needless Words (in C++)

In C++ as in life, some people tend to use more words than they need to. As Strunk and White put it: Omit needless words.

Here’s an example I saw again yesterday in a recent peer-reviewed online magazine article showing how to write some C++ code to solve a particular problem. There’s nothing wrong with the code I’m going to show; but it tries to use a technique to "save typing" while accomplishing the opposite because of being unaware of a clever little C++ feature.

I’ll rearrange the particular code I saw to disguise the example (lots of people do this, and it would be unfair to target one person). The code started something like this:

template<
  typename T1,
  typename T2,
  typename T3,
  template <typename A1, typename A2 >class CreationPolicy,
  template <typename A1, typename A2 >class MemoryPolicy,
  template <typename A1, typename A2 >class SnarkPolicy,
  template <typename A1, typename A2 >class HumptyPolicy,
  typename SomeHelperType,
  typename StillAnotherType>
class MyClass
{

So far, so good; these words are needed for the purpose the author is trying to accomplish (it’s a heavy-duty template with enough type parameters to make Andrei proud).

Next comes the definition of MyClass, and some part of that may want to refer to "my type (this particular MyClass instantiation)." Now, it could spell it out as "MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType >" — but, yuck, who wants to write all that every time?

In an attempt to avoid that verbosity, the class author next writes a convenience typedef:

  // Typedef — to save typing (?)
  typedef MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType > ThisClass;

(Some of you may be about to interrupt our program with a "but why would he write that when he can just…" — right, but just wait for it.)

Then the code can go on to name "this particular MyClass instantiation" easily, say to pass "my type" to someone else:

public:
  static bool SomeFunc()
  {
    // instantiate some other template with "my type"
    vector<ThisClass> v;

    // call another static function of "my own type"
ThisClass::OtherFunc();

    … more code …
  }

There are two cases of needless words here.

First, the typedef doesn’t save any writing on the call to "ThisClass::OtherFunc()," because that call doesn’t need any qualification at all. It could simply have been written as "OtherFunc();" since that call is already inside MyClass.

Second, and more to the point, the typedef is completely unnecessary in the first place. Why? Because inside a class template, the simple name of the class template automatically implies "this instantiation" including the full parameter list. That is, in the above example there is no difference between typing

MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType >

and just typing

MyClass

when inside the template.

So the typedef is completely unnecessary, and the original code:

  // Typedef — to save typing (?)
  typedef MyClass< T1, T2, T3, CreationPolicy, MemoryPolicy, SnarkPolicy, HumptyPolicy, SomeHelperType, StillAnotherType > ThisClass;

public:
  static bool SomeFunc()
  {
    // instantiate some other template with "my type"
    vector<ThisClass> v;

    // call another static function of "my own type"
ThisClass::OtherFunc();

    … more code …
  }

could have been written simply (and a bit more clearly) without any typedef, using just the class template’s name or nothing at all:

public:
  static bool SomeFunc()
  {
    // instantiate some other template with "my type"
    vector<MyClass> v;

    // call another static function of "my own type"
    OtherFunc();

    … more code …
  }

Ironically, the typedef not only didn’t save typing, but actually added a little.

Sometimes less is more. Where possible, use fewer words.

Webcast (via Intel) on September 25

On Tuesday September 25, I’ll be doing the kickoff webcast in Intel’s fall 2007 developer "webinar" series. It’ll be closely based on a talk I’ve given before on "Software and the Concurrency Revolution," but I’m going to update-and-trim material to try to leave more time for some interactive discussion. Here’s the info:

Webcast: "The Concurrency Revolution"

Date: Tuesday, September 25, 2007
Time: 9:00am U.S. Pacific Time (click here for more time zones) *
Length: 1 hour

Although driven by the industry-wide shift to multi-core hardware architectures, concurrency is primarily a software revolution. We are now seeing the initial stages of the next major change in software development, as over the next few years the software industry brings concurrency pervasively into mainstream software development, just as it has done in the past for objects, garbage collection, generics, and other technologies. Sutter summarizes the issues involved, gives an overview of the impact, and describes what to expect over the coming decade.

They’ll be doing a concurrency-related webcast every two weeks. The second talk in the fall series will be "Steps to Parallelism NOW" by James Reinders, author of the new book Threading Building Blocks about Intel’s cool (and recently open-sourced) C++ template library for concurrency. Should be good.

Footnotes

* I love timeanddate.com.

Trip Report: July 2007 ISO C++ Standards Meeting

The ISO C++ committee met in Toronto on July 15-20. Here’s a quick summary of what we did, and information about upcoming meetings.

Features voted into draft C++0x

enum class (N2347)

This is an extension from C++/CLI that allow writing enums that has a predictable size and underlying type, has its own scope (to the enumerators don’t get injected into the enclosing scope where they can conflict with similar names), and doesn’t have a nasty implicit conversion to int (or anything else). The proposal was written by David Miller, myself, and Bjarne.

Saving exceptions (N2179)

Added language and library support for saving an exception: This feature is useful in plain old sequential code if you want to catch and store an exception to be rethrown later. But it’ll be especially useful in concurrent code, so that we can catch an exception and transport it across threads (e.g., when waiting on an asynchronous function call).

constexpr (N2235 and N2349)

This feature permits generalized constant expressions — or, in English, being able to write your own compile-time constants that really act like compile-time constants. To illustrate, here’s one simple example from the paper:

constexpr int square(int x) { return x * x; }

What’s the point? Now if you call square() with an argument that is a compile-time constant, then the result of calling square() is still a compile-time constant, and you can use it anywhere you can use compile-time constants, such as specifying the length of an array:

float arr[ square(9) ]; // ok, array of length 81

Note that the above is not a C99 variable length array. It’s a normal fixed-size array, but we have more flexibility and convenience in specifying its size.

See the linked paper for more details and examples. And to see how this new language feature is immediately also being used in the C++ standard library, here’s your source: N2349, "Constant Expressions in the Standard Library — Revision 2."

decltype (N2343 and N2194; for discussion see N2115 and N1978)

The decltype feature lets you get the type of an expression, so that you can do things with the type (e.g., declare more variables of that type) without knowing in advance what the type is or how to spell it.

This is a great boon to generic programming with templates, and without the runtime cost of reflection in other languages. For example, say that you’re handed an iterator, and you want to know what type it refers to. Today, you need to ask the iterator for its value_type, which is a manual "traits" convention everyone is expected to follow when writing and using iterators:

template<typename Iter>
void f( Iter it ) {
Iter::value_type v = *it;
  …
}

With decltype, we could instead write:

template<typename Iter>
void f( Iter it ) {
decltype(*it) v = *it;
  …
}

Are you curious to see how decltype is being used in the C++0x standard library itself? Here’s the paper for you: N2194, "decltype for the C++0x Standard Library."

alignof (N2341)

A nice portable way to get aligned storage and inquire about the alignment requirements of types without performing system-dependent backflips.

=default and =delete (N2346 and N2292)

If you’ve ever wished you could control the four default special member functions (default constructor, copy constructor, copy assignment, and destructor) and especially how they’re inherited from base classes, this is the paper for you.

How could these be useful in the C++0x standard library itself do you ask? Here’s where to find the answer: N2292, "Standard Library Applications for Deleted Functions."

Some other approved features

  • N2340 "C99 Compatibility : _ _ func _ _ and predeclared identifiers (revision 2)"
  • N2342 "POD’s Revisited; Resolving Core Issue 568 (Revision 5)"
  • N2293 "Standard Library Applications for Explicit Conversion Operators"
  • N2348 "Wording for std::numeric_limits<T>::lowest()"
  • N2350 "Container insert/erase and iterator constness (Revision 1)"
  • N2351 "Improving shared_ptr for C++0x, Revision 2"
  • N2299 "Concatenating tuples" (except change the name of the four functions named concatenate to tuple_cat)
  • N2007 "PROPOSED LIBRARY ADDITIONS FOR CODE CONVERSION" (hey, don’t blame me for screaming, that’s the title…)
  • N2308 "Adding allocator support to std::function for C++0x" (except change the pass-by-value Allocator argument to pass-by-const-reference)
  • N2321 "Enhancing the time_get facet for POSIX® compatibility, Revision 2"
  • N2353 "A Specification for vector<bool>" into the C++0X Working Paper. (After all, no meeting would be complete without some discussion of vector<bool>…)

Next Meetings

Here are the next meetings of the ISO C++ standards committee, with links to meeting information where available.

  • October 1-6: Kona, Hawaii, USA [N2289]
  • February 24-29, 2008: Bellevue, Washington, USA
  • June 8-13, 2008: Sophia Antipolis, France

The meetings are public, and if you’re in the area please feel free to drop by.