$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
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
> http://cci.lbl.gov/~rwgk/tmp/enhanced_pod_proposal.html
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];
    public:
        Complex(double r=0, double i=0) { value = { r, i ); }
        ...
    };
and
    Complex cx_array[N];
you could safely do
    some_fun((double*)cx_array,N);
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
restrictions.
------------------------------------------------------------------------
  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.
  [Example:
  #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)