Topic: Trivial default constructors and unions


Author: phalpern@truffle.ma.ultranet.com (Pablo Halpern)
Date: 1996/08/23
Raw View
In the April 1995 DWP, in the section about unions [class.union],
members of a union are restricted as follows:

  ... An object of a class with a non-trivial default construc
  tor  (_class.ctor_),  a non-trivial copy constructor (_class.copy_), a
  non-trivial destructor (_class.dtor_), or a non-trivial  copy  assign
  ment  operator  (_over.ass_,  _class.copy_)  cannot  be  a member of a
  union, nor can array of such objects.

In the secton about constructors [class.ctor], a "trivial" default
constructor is defined as follows:

  ...
  A [default] constructor  is  trivial  if  it is an implicitly-declared
  default constructor and if:

  --its class has no virtual functions (_class.virtual_) and no  virtual
    base classes (_class.mi_), and

  --all  the direct base classes of its class have trivial constructors,
    and

  --for all the nonstatic data members of its class that  are  of  class
    type  (or array thereof), each such class has a trivial constructor.

  Otherwise, the constructor is non-trivial.

This definition of a trivial default constructor leads to problems where
simple classes cannot be used as members of unions, even though the
default constructor doesn't do anything. The problem stems from the
following conflict:

1. Sometimes it is necessary to explicitly declare a default constructor
   or else the class will not have a default constructor

2. Such an explicitly declared default constructor cannot, by the above
   definition, be trivial.

For example, the following class cannot be used in a union because it
has no default constructor:

   class complex
   {
       double real, imaginary;
     public:
       complex(double re, double im = 0.0);
       // ...
   };

If we add a default constructor:

   complex() { }

it still cannot be used in a union because the default constructor is
not trivial. Note that this problem *does not* occure for the copy
constructor because *every class* has a copy constructor and it is never
necessary to declare one yourself if the implicitly defined one will
suffice. Similarly, it is not a problem for the destructor.

My proposed solution:

Change the wording of the definition of a trivial default constructor to
something like the following (I tried to make this less verbose, but
failed):

  An *empty* constructor is one that is inline, has no
  parameters (not even default parameters), no explicit member
  initialization list, and no statements or declarations within the
  constructor body. An empty constructor for class X would therefore be
  defined:
      class X
      {
        X() { }
      };
  A default constructor  is  trivial  if  it is an implicitly-declared
  default constructor or a public empty constructor and if:

     [ bullet list the same as in existing text (above) ]

What do people think about this problem/solution? It seems like a small
change to me. The only change for the compiler writers is to be able to
recognize an empty constructor (not that it's easy, but it's not as
nearly as hard as something like partial template specialization). Are
there any committee members on line that could sponsor such a change?
Should I make a formal proposal?

-------------------------------------------------------------
Pablo Halpern                   phalpern@truffle.ultranet.com

I am self-employed. Therefore, my opinions *do* represent
those of my employer.
---
[ comp.std.c++ is moderated.  To submit articles: Try just posting with your
                newsreader.  If that fails, use mailto:std-c++@ncar.ucar.edu
  comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
  Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
  Comments? mailto:std-c++-request@ncar.ucar.edu
]