Boost logo

Boost :

From: Greg Colvin (gcolvin_at_[hidden])
Date: 2002-03-17 21:58:09

"David Abrahams" <david.abrahams_at_[hidden]> writes:
> Ralf and I have authored this paper for the upcoming C++ committee
> meeting

Excellent job, thanks. It has gotten me thinking about what an enhanced
POD should be allowed to do. For reference I have appended the relevant
definitions from the standard.

The first thing I notice is that PODs are a type of aggregate, and that
aggregates are already forbidden to have constructors. So one way to
allow a POD to have constructors would be to drop that restriction, but
I believe the purpose of that restriction is to prevent users from
circumventing user-declared constructors by using an initializer-clause.
The restriction against private and protected members partially follows
from having no constructor with which to initialize such members, and
also allows compilers more freedom in laying out classes with multiple
protection levels. I think that restriction could be relaxed to allow
for all-protected or all-private classes, which would then a derived
class or member functions or friend functions to initialize them. The
restriction against base classes and virtual functions also provides
more layout freedom.

So we have several restrictions just on aggregates that we might (or
very well might not) want to relax, including the restriction against
constructors that we most want to relax.

If we don't want to relax the prohibition on aggregate destructors then
we will have a definitional impasse. One way around the impasse might be
to declare that non-aggregate classes, whose data members are all PODs at
the same level of protection, and which have no base classes or virtual
functions, are also PODs. So that, for example, given

    class Complex {
        double value[2];
        Complex(double r=0, double i=0) { value = { r, i ); }


    Complex cx_array[N];

you could safely do


An aggregate that is a POD is also restricted from contain any data
members that have been, as Mike Ball put it, "touch with C++ magic",
such as pointers to member functions, non-POD members, and references.
Again, this allows implementers more freedom, while allowing PODS to be
freely copied around as contiguous chunks of memory. The restriction
against user-defined destructors further guarantees that such chunks can
be freely abandoned. So I doubt we will want to relax any of these

  9 Classes [class]

4 ... A POD-struct is an aggregate
  class that has no non-static data members of type pointer to member,
  non-POD-struct, non-POD-union (or array of such types) or reference,
  and has no user-defined copy assignment operator and no user-defined
  destructor. Similarly, a POD-union is an aggregate union that has no
  non-static data members of type pointer to member, non-POD-struct,
  non-POD-union (or array of such types) or reference, and has no user-
  defined copy assignment operator and no user-defined destructor. A
  POD class is a class that is either a POD-struct or a POD-union.

  8.5.1 Aggregates [dcl.init.aggr]

1 An aggregate is an array or a class (clause _class_) with no user-
  declared constructors (_class.ctor_), no private or protected non-
  static data members (clause _class.access_), no base classes (clause
  _class.derived_), and no virtual functions (_class.virtual_).

2 When an aggregate is initialized the initializer can be an initial-
  izer-clause consisting of a brace-enclosed, comma-separated list of
  initializers for the members of the aggregate, written in increasing
  subscript or member order. If the aggregate contains subaggregates,
  this rule applies recursively to the members of the subaggregate.

  3.9 Types [basic.types]

1 [Note: _basic.types_ and the subclauses thereof impose requirements on
  implementations regarding the representation of types. There are two
  kinds of types: fundamental types and compound types. Types describe
  objects (_intro.object_), references (_dcl.ref_), or functions
  (_dcl.fct_). ]

2 For any complete POD object type T, whether or not the object holds a
  valid value of type T, the underlying bytes (_intro.memory_) making up
  the object can be copied into an array of char or unsigned char.13) If
  the content of the array of char or unsigned char is copied back into
  the object, the object shall subsequently hold its original value.
  #define N sizeof(T)
  char buf[N];
  T obj; // obj initialized to its original value
  memcpy(buf, &obj, N); // between these two calls to memcpy,
                                  // obj might be modified
  memcpy(&obj, buf, N); // at this point, each subobject of obj of scalar type
                                  // holds its original value
   --end example]

3 For any POD type T, if two pointers to T point to distinct T objects
  obj1 and obj2, if the value of obj1 is copied into obj2, using the
  13) By using, for example, the library functions (_lib.headers_) mem-
  cpy or memmove.

  memcpy library function, obj2 shall subsequently hold the same value
  as obj1. [Example:
  T* t1p;
  T* t2p;
                                  // provided that t2p points to an initialized object ...
  memcpy(t1p, t2p, sizeof(T)); // at this point, every subobject of POD type in *t1p
                                  // contains the same value as the corresponding subobject in
                                  // *t2p
   --end example]

4 The object representation of an object of type T is the sequence of N
  unsigned char objects taken up by the object of type T, where N equals
  sizeof(T). The value representation of an object is the set of bits
  that hold the value of type T. For POD types, the value representa-
  tion is a set of bits in the object representation that determines a
  value, which is one discrete element of an implementation-defined set
  of values.14)

Boost list run by bdawes at, gregod at, cpdaniel at, john at