Topic: Const constructors


Author: rac@intrigue.com (Robert Coie)
Date: 1995/07/21
Raw View
Apologies if this has been discussed before, but I don't recall it.  Has a
proposal ever been made to allow const constructors (i.e., constructors
that are only allowed to be invoked when creating const objects)?

This came up when dealing with a class that represents a reference-counted
resource:

struct A
{
   A();
   A( const A & );

   void mutating_func();
   void inspection_func() const;

   // refcounted shared data pointer
};

I have problems returning objects of class A from functions in
circumstances where I want to insure that the shared resource is not
modified through the returned object.  I thought it would be elegant if
one could do the following:

struct A
{
   A();
   A( const A & ) const;
   A( A & );
   // etc
};

const A returns_constA();

int main()
{
   A a1 = returns_constA();         // illegal
   const A a2 = returns_constA();   // allowed
   a2.inspection_func();            // OK
   a2.mutating_func();              // nope, a2 is const
}

The only solution I could come up with under the current C++ language
definition is to have an artificial class:

struct AC
{
   AC();
   AC( const AC & );
   void inspection_func() const;
   // data must go here
};

struct A : public AC
{
   A();
   A( const A & );
   void mutating_func();
};

AC returns_constA();

This rapidly becomes unwieldy because in real life A is the base class for
several other classes, and to avoid duplicated data I end up with a
virtual base that contains data.  I try to follow John "Max" Skaller's
rule that virtual bases should not be data-bearing and should be
initialized with default constructors, so I'm stuck.

Robert Coie                              rac@intrigue.com
Implementor, Intrigue Corporation     AppleLink: INTRIGUE





Author: herbs@interlog.com (Herb Sutter)
Date: 1995/07/22
Raw View
In article <rac-2107951124000001@intrigue.intrigue.com>,
   rac@intrigue.com (Robert Coie) wrote:
>Apologies if this has been discussed before, but I don't recall it.  Has a
>proposal ever been made to allow const constructors (i.e., constructors
>that are only allowed to be invoked when creating const objects)?

Yes, many times. :-)  A ctor, by definition, changes the state of an object
because it creates the state of an object (note that this claim holds for both
logical and physical const-ness), so really there's no such thing as a const
ctor.  In practice, wanting to construct an object differently depending on
whether that object is const or not is extremely rare.  First ask yourself why
you want to do it, and whether that reason isn't due to some flaw in the
design.

Now, assuming you're slept on it and you still really want to prevent const
objects to be copied to non-const ones (there isn't a better way to design
your object model? why should your reference-counting require this?), then
just divorce construction from initialisation.  You continued:

>This came up when dealing with a class that represents a reference-counted
>resource:
>
>struct A
>{
>   A();
>   A( const A & );
>
>   void mutating_func();
>   void inspection_func() const;
>
>   // refcounted shared data pointer
>};
>
>I have problems returning objects of class A from functions in
>circumstances where I want to insure that the shared resource is not
>modified through the returned object.  I thought it would be elegant if
>one could do the following:
>
>struct A
>{
>   A();
>   A( const A & ) const;
>   A( A & );
>   // etc
>};
>
>const A returns_constA();
>
>int main()
>{
>   A a1 = returns_constA();         // illegal
>   const A a2 = returns_constA();   // allowed
>   a2.inspection_func();            // OK
>   a2.mutating_func();              // nope, a2 is const
>}

Divorcing construction from initialisation just means a separate Init() (or
whatever) member function that client code uses to initialise a constructed
object before it can be used.  Now you can have const and non-const versions,
and readily determine whether you are initialising a const or non-const
object.  You can now also achieve the result you're trying for above (namely
that a non-const object can't be copied from a const object) because the
objects know, by a stored flag set in Init(), whether they are const or not.

True, client code needs to be aware of two-stage construction, but it's not as
bad as the alternative (extra class) you found.  For example:

enum Constness { Const = 1, Nonconst = 0, Undetermined = -1 };

struct A
{
   A() { constness = Undetermined; };
   Init(const A& other)       {
      constness = Nonconst;
      // copy from other
   };
   Init(const A& other) const {
      constness = Const;
      if (other.constness == Const)
         // copy from other
      else
         // throw an exception
   };

   void mutating_func() {};
   void inspection_func() const {};

private:
   Constness constness;
};

const A returns_constA();

int main()
{
   A a1;
   a1.Init(returns_constA());       // illegal: Init() throws exception
   const A a2;
   a2.Init(returns_constA());       // allowed
   a2.inspection_func();            // OK
   a2.mutating_func();              // nope, a2 is const
   return 0;
}

Of course, since you're doing all this work to avoid allowing const objects to
get copied to non-const ones, don't forget to write operator=() appropriately.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Herb Sutter                 2228 Urwin, Ste 102         voice (416) 618-0184
Connected Object Solutions  Oakville ON Canada L6L 2T2    fax (905) 847-6019





Author: sakkinen@jyu.fi (Markku Sakkinen)
Date: Thu, 23 Apr 1992 06:10:16 GMT
Raw View
In article <ROBERTK.92Apr15152806@rkrajewski.lotus.com> robertk@rkrajewski.lotus.com (Robert Krajewski) writes:
>Please excuse if this is a frequently asked question, but has
>there been any activity on getting const constructors (that
>is, constructors that produce const objects) into the language ?

Could you explain more what you are actually wanting?
Ordinary constructors can be used for const objects just as well
as for non-const ones, so I cannot immediately see any problem.

----------------------------------------------------------------------
Fight against terrorism: destroy the army HQ in Belgrade!

Markku Sakkinen (sakkinen@jytko.jyu.fi)
       SAKKINEN@FINJYU.bitnet (alternative network address)
Department of Computer Science and Information Systems
University of Jyvaskyla (a's with umlauts)
PL 35
SF-40351 Jyvaskyla (umlauts again)
Finland
----------------------------------------------------------------------