Peeking Further into C++00X

Expanding the Scope of C++!

In last month's installment, you covered the context of C++ standards development, TR1, and the rationale for expanding the scope of C++. The next C++ standard, code-named "C++00X", is heading down the home stretch towards ratification. Currently, it is expected to be named C++09 as of the latest report (N2336) released in July 2007. In this article, you peek further into what C++00X means to the average C++ programmer in the trenches. Because there are dozens of WG21 proposals on the table as of this writing, I will focus this article solely on proposals that were greenlighted at the July 2007 meeting, rather than discussing features that have been integrated in past months' or years' work.

Generalized Constant Expressions

Recently integrated into the working paper, Generalized Constant Expression represents the fourth iteration of attempts to normalize the working of constants in the C++ language. Although constants are everywhere in C++ programs (including const and enum), their participation in expressions has a certain degree of ambiguity under current rules. N2335 addresses all of these concerns in four specific categories:

  • Improving type-safety and portability for code requiring compile time evaluation
  • Improving support for systems programming, library building, generic programming
  • Simplifying the language definition in the area of constant expression to match existing practice
  • Removing embarassments from existing Standard Library components (namely #include limits)

Fixing the Bitmask

One problem this fixes is the bitmask type when it's implemented by an enum with overloaded operators. This is just one of three allowable implementations by the compiler; when it's used, the bitmask is no longer constant in the sense that it can be evaluated at compile time. The new constexpr keyword addresses this and many other things that allow for compile-time optimization of things that formerly were deferred until execution time.

When const Isn't

It is possible to be surprised by expressions that (to someone) "look const" but are not. For example, consider

   struct S {
      static const int size;
   };

const int limit = 2 * S::size;    // dynamic initialization
const int S::size = 256;
// dynamic initialization
const int z = numeric_limits<int>::max();

Here, S::size is indeed initialized with a constant expression, but that initialization comes "too late" to make S::size a constant expression; consequently, limit may be dynamically initialized. Again, constexpr will come to the rescue.

Constant-Expression Functions

The new distinction Constant-Expression Function marries the best attributes of #define macro functions with the type safety, predictability of const, and guaranteed compile-time evaluation. In particular, a function is a constant-expression function if and only if it satisfies these criteria:

  • It returns a value (in other words, not void);
  • Its body consists only of a single statement of the form.
  • return expr;

    and every single thing that combines to produce expr is also constant.

  • It is declared with the keyword constexpr.
  • It cannot be called before it is defined, thus recursion is not allowed.

Interestingly, a constant-expression function may be called with non-constant expressions (for example, variables). In that case, there is no requirement that the resulting value be evaluated at compile-time.

Here are some examples:

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

constexpr int abs(int x)
   { return x < 0 ? -x : x; }    // legal

constexpr int next(int x)
   { return ++x; }    // error: increment cannot be evaluated at
                      // compile time

constexpr int g(int n)    // error: body not just ''return expr''
{
   int r = n;
   while (--n > 1) r *= n;
   return r;
}

constexpr int fac(int x)
   { return x > 2 ? x * fac(x - 1) : 1; }    // error: fac() not
                                             // defined before use

C99 Compatibility : __func__ and Predeclared Identifiers

The 1999 revision of the C standard introduced the concept of 'a predeclared identifier'. N1970 carries that concept forward into C++ in the name of upward compatability, an attribute that the standards committee holds dear. In the past, the role of these diagnostic aids was a part of the macro preprocessor, a mechanism that the standards committee tries to relegate as much as possible. Basically, these predeclared identifiers allow you to construct intelligent error messages that point out the line number, file name, and function name where a problem is taking place. __func__ is the equivalent of a local declaration like:

static const char __func__[] = "function-name";

Traditionally, the double_underscore ("__") denotes a compiler vendor-specific identifier, although it is now a universal identifier in this particular case. Here's a typical usage:

include <cstdio>
namespace example
{

   void myfunc()
   {
      std::printf("Error in function %s\n", __func__);
      /* ... */
   }

}

WG21 proposal N2220 provides further clarification of how __func__ changes over the course of the runtime environment:

namespace N { void f(); }
void N::f() { }                   // __func__ is "f"

struct S {
   S() : s(__func__) { }          // okay, s points to "S"
   ~S() { }                       // __func__ is "~S"
   operator int() { }             // __func__ is "conversion operator"
   template<class T> int g();
   const char *s;
};
S operator +(S,S) { }             // __func__ is "operator+"
template<> int S::g<int>() { }    // __func__ is "g"

Peeking Further into C++00X

Tracking the PODs

One thing missing in the standards as of late is a clear definition of what constitutes a POD object. POD stands for Plain Old Data and begs the question "What kinds of things can you do with classes that resemble old C structs for all intents and purposes?" It is not a silly question because compiler optimization, STL implementation efficiency, and thread-safe operation rely heavily on knowing when something can be bitwise-copied, like a dumb struct and when the consequences of ctors and dtors comes into requirement. It has evolved over time to N2324, which provides keywords for expressing atomic operations, a key requirement for thread-safe code. A discussion of POD semantics lies outside of what I can cover in this article.

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

Even More Runtime Type Information

The decltype() is a great boon to generic programming with templates, and without the runtime cost of reflection in other languages (think of TypeOf() in .NET parlance). 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, you could instead write:

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

This is all in service of making C++ code easier to write and with exposing fewer awkward implementation details. On a similar note, you may notice the explosion of typedefs needed to make using certain STL types legible. This is addressed by the new auto keyword that basically says "Make me a variable of the correct return type" and is bound to save hours of searching manuals and copy/paste madness. Instead of writing

for (vector<int>::const_iterator itr = myvec.begin();
   itr != myvec.end(); ++itr)

the programmer can use the shorter

for (auto itr = myvec.begin(); itr != myvec.end(); ++itr)

Which form would you try to teach new programmers trying to learn C++? Yes, I think so too!

About the Author

Victor Volkman has been writing for C/C++ Users Journal and other programming journals since the late 1980s. He is a graduate of Michigan Tech and a faculty advisor board member for the Washtenaw Community College CIS department. Volkman is the editor of numerous books, including C/C++ Treasure Chest and is the owner of Loving Healing Press. He can help you in your quest for open source tools and libraries; just drop an e-mail to sysop@HAL9K.com.



About the Author

Victor Volkman

Victor Volkman has been writing for C/C++ Users Journal and other programming journals since the late 1980s. He is a graduate of Michigan Tech and a faculty advisor board member for Washtenaw Community College CIS department. Volkman is the editor of numerous books, including C/C++ Treasure Chest and is the owner of Loving Healing Press. He can help you in your quest for open source tools and libraries, just drop an e-mail to sysop@HAL9K.com.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: October 23, 2014 @ 12:00 p.m. ET / 9:00 a.m. PT Despite the current "virtualize everything" mentality, there are advantages to utilizing physical hardware for certain tasks. This is especially true for backups. In many cases, it is clearly in an organization's best interest to make use of physical, purpose-built backup appliances rather than relying on virtual backup software (VBA - Virtual Backup Appliances). Join us for this eSeminar to learn why physical appliances are preferable to …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds