Tracking the standard

By: Steve Downey

Abstract: ANSI's C++ committee continues to address inconsistencies and rough spots in the standard -- and you can help! By Steve Downey.

Tracking the standard

ANSI's C++ committee continues to address inconsistencies and rough spots in the standard. 

The ANSI C++ committee finished work on the language standard in November 1997. The standard was duly approved by ISO and is now available in electronic form -- you can buy an electronic copy for US$18 from the ANSI Web site.

Since the work of the committee appears to be done, you might be surprised to learn that it is still meeting twice a year. I was.

I assumed at first that they were working on the next version of the standard. But no -- that work won't begin for at least five years. The committee is processing defect reports.

It turns out that the standard as adopted includes inconsistencies, ambiguities, misspellings, and omissions. The committee is serving as a central collection site for reports of these glitches.

Some of the submitted reports are fascinating, while others are merely instructive. Go ahead and check them out -- the committee makes them available at its home page. Each defect report concludes with a proposed resolution or a rationale for why the defect will not be addressed.

A defect report is most commonly consigned to the "do not address" pile when the particular spec is not actually defective or when the defect report is actually a request for an extension to the standard.

For example, someone reported to the committee that bitsets can not be initialized with a string literal. Consider this code:

#include <bitset>
using namespace std;
bitset<32> b("111111111");

How does it work? It doesn't -- it will fail to compile. Fixing it would require a constructor that takes a const char * as an argument. This "defect" is actually a request for an extension, not an error that can be repaired within the standard.

It's worth reading through the lists, just as it's worth reading the specification itself. You wind up with a clearer understanding of what is promised by the language and what is not.

A good example is library issue 69, "Must the elements of a vector be contiguous?" Take a look at this code:

#include <vector>
using namespace std;
vector<double> v(5);
double * p = &v[0];

Can you use p as a pointer to the array of doubles inside the vector? That would be useful when connecting to older C-style libraries, where it is typical to send a pointer to a buffer and an element count. For example:

stuff_down_socket(s, &v[0], v.size() * sizeof double);

This cast has worked for all existing implementations of the standard C++ library, going all the way back to the HP STL. It's the natural implementation of a std::vector. But it turns out that this behavior isn't guaranteed in the standard as written. The committee has answered that, yes, this is guaranteed to work with a conforming implementation.

Another interesting example is language issue 35, "Definition of default-initialization." Take the following code:

struct S1
{
  double x;
};

struct S2
{
  double x;
  string s;
};

void func()
{
  double x1 = S1().x;
  double x2 = S2().x;
  S1 s1;
  double x3 = s1.x;
};

According to the specification, x1 is well-defined. It is always 0 because S1() default-initializes everything. However, the value of x2 is undefined. This can be very bad on systems where random bit patterns in a floating-point number can cause a trap and terminate the program. The problem is caused by the addition of the member s, a string, which means that S2 isn't a POD-type. (POD? Why, plain old data, of course, as defined in the C++ standard, section 1.8, paragraph 5, footnote 4. Go ahead, look it up.)

The intent of the standard was to make sure that things got initialized properly, so the wording of the standard will be changed slightly to ensure that all class types, not just POD types, are initialized to zero.

(Note, however, that s1.x always was and still is uninitialized, so using it to initialize x3 is undefined behavior. And undefined behavior means anything can happen, from your program crashing to the computer executing the halt-and-catch-fire instruction, HCF.)

Of course, fixing the standard is just half the battle. Many popular compilers are nonconforming -- they don't correctly initialize even x1. So test before you count on this behavior.

If you have a defect to report, check out the comp.std.c++ FAQ page.


Server Response from: ETNASC03