Topic: proposal !const (not const)


Author: gregw@cssc-syd.tansu.com.au (Greg Wilkins)
Date: 2 Apr 1993 17:50:04 +1000
Raw View
I have a problem with const.  Currently, when an object is const -
absolutely none of its members may be modified, or non-const member
functions called.  To me, is too strict an overides the OO concept of
separating interface from implementation. What const should prevent you
from doing is modifying members that represent the Value(big V) of the
object, but should not prevent you from modifying the value(little v)
of members used for implementation.

Thus it is awkward to implement classes that have some form of lazy
evaluation of generated data.  Eg Consider a class which represents the
name of a machine on a network.  A member of that class could return
the IP address of the machine, however consulting a DNS for the IP is
time consuming, and once done, the IP address could be stored within
the object for future use.  Thus the IP address is fetched only if it
is required, and cached there after.   Unfortunately, this prevents
passing such a object as a const, as the callee may wish to know the IP
address, which may not have been previously fetched.

Thus what I would like to have, are members that I am allowed to modify
under wider conditions, (not simply by casting away from a const
object).  Below are two code fragments, the first represents the way I
would like to write such objects, using my proposed extension of !const
(meaning this member is not const and is not bound by const
declarations of the containing object).  Is this a bad idea?

The second code fragment is how I currently do it in C++ V3.0, using
nested classes.  Is there a more elegant solution to this problem?

thanks in advance for any comments,

Greg Wilkins
-gregw@cssc-syd.tansu.com.au



// PROPOSED EXTENSION
#include <iostream.h>

typedef int Bool;
const Bool FALSE= (1==2);
const Bool TRUE= (1==1);

class Data
{
  public:
    Data(int data);

    int getData() const  {return data;}
    int getGenData() const {return genData();} // OK as it is a !const

  private:
    int data;                    // The Value of the object

    int genData() !const;        // function not bound by const, which returns
                                 // a generated value of the object
    !const Bool generated;       // data not bound by const
    !const int  gData;           // ditto, which caches generated data
};

Data::Data(int d)
{
    data = d;           // set Value
    generated = FALSE;  // generated data not set yet
}

int Data::genData() !const
{
    if (!generated)
    {
 // perform time consuming calculation that you only want to
 // do if required, and then only once!
 cerr << "Generating extra data" << endl;
 gData = (data.data)+1;  // OK as it is !const
 generated=TRUE;  // OK as it is !const
        // data=0; would be an Error as only !const members can be modified in a
        // !const member func, which may or may not have been called on a const
        // object.
    }
    return gData;
}

void main()
{
    const Data data(3);

    cout << data.getData() << endl;
    cout << data.getGenData() << endl;  // generates the genData
    cout << data.getGenData() << endl;  // uses cached genData
}





// ======================================================================
// The way I currently do it in C++ 3.0
// This should compile

#include <iostream.h>

typedef int Bool;
const Bool FALSE= (1==2);
const Bool TRUE= (1==1);

class Data
{
  public:
    Data(int data);
    ~Data();

    int getData() const  {return data;}
    int getGenData() const {return generatedData->genData(*this);}

  private:
    int data;

    class GeneratedData
    {
      public:
 GeneratedData() {generated = FALSE;}
 int genData(const Data&);

      private:
 Bool generated;
 int gData;
    } *generatedData;
    friend class Data::GeneratedData;
};

Data::Data(int d)
{
    data = d;
    generatedData = new GeneratedData;
}

Data::~Data()
{
    delete generatedData;
}

int Data::GeneratedData::genData(const Data& data)
{
    if (!generated)
    {
 // perform time consuming calculation that you only want to
 // do if required, and then only once!
 cerr << "Generating extra data" << endl;
 gData = (data.data)+1;
 generated=TRUE;
    }
    return gData;
}

void main()
{
    const Data data(3);

    cout << data.getData() << endl;
    cout << data.getGenData() << endl;  // generates the genData
    cout << data.getGenData() << endl;  // uses cached genData
}








Author: steve@taumet.com (Steve Clamage)
Date: Sat, 3 Apr 1993 16:48:52 GMT
Raw View
gregw@cssc-syd.tansu.com.au (Greg Wilkins) writes:


>I have a problem with const.  Currently, when an object is const -
>absolutely none of its members may be modified, or non-const member
>functions called.  To me, is too strict an overides the OO concept of
>separating interface from implementation. What const should prevent you
>from doing is modifying members that represent the Value(big V) of the
>object, but should not prevent you from modifying the value(little v)
>of members used for implementation.

This is the "logical constness" versus "bitwise constness" problem
which has been discussed in various circles for some time.  There are
proposals for addressing the problem under discussion by the C++
Committee.  It seems likely that something  will be adopted
to address the situation.
--

Steve Clamage, TauMetric Corp, steve@taumet.com




Author: mat@mole-end.matawan.nj.us
Date: Sat, 3 Apr 1993 18:57:23 GMT
Raw View
In article <1pgr7c$lf5@minotaur.cssc-syd.tansu.com.au>, gregw@cssc-syd.tansu.com.au (Greg Wilkins) writes:
>
> I have a problem with const.  Currently, when an object is const -
> absolutely none of its members may be modified, or non-const member
> functions called.  ...  ... What const should prevent you from doing is
> modifying members that represent the Value(big V) of the object, but ...
> not ... from modifying the ... of members used for implementation.

> Thus it is awkward to implement classes that have some form of lazy
> evaluation of generated data.  ...

It's under consideration by x3j16/WG21 already.
--
 (This man's opinions are his own.)
 From mole-end    Mark Terribile

 mat@mole-end.matawan.nj.us, Somewhere in Matawan, NJ




Author: marc@offline.be (Marc Duponcheel)
Date: 2 Apr 93 22:51:34 PST
Raw View
In article <1pgr7c$lf5@minotaur.cssc-syd.tansu.com.au> gregw@cssc-syd.tansu.com.au (Greg Wilkins) writes:
>
> I have a problem with const.
>
> Thus what I would like to have, are members that I am allowed to modify
> under wider conditions, (not simply by casting away from a const
> object).  Below are two code fragments, the first represents the way I
> would like to write such objects, using my proposed extension of !const
> (meaning this member is not const and is not bound by const
> declarations of the containing object).  Is this a bad idea?
>


To be honest, I once had the SAME proposal in mind but my friend Jan Joos
simlpy argued :

What if we cast this to (Data *) ONLY in genData ?  After all genData is
private so nobody cares and nobody sees it (the user does NOT hav to cast)!

by the way, I could not compile the statement :
 gData = (data.data)+1;

#include <iostream.h>

typedef int Bool;
const Bool FALSE= (1==2);
const Bool TRUE= (1==1);

class Data
{
  public:
    Data(int data);

    int getData() const     {return data;}
    int getGenData() const  {return genData();}

  private:
    int data;                    // The Value of the object

    int genData() const;         // const function
                                 // a generated value of the object
    Bool generated;              // data not bound by const
    int  gData;                  // ditto, which caches generated data
};

Data::Data(int d)
{
    data = d;           // set Value
    generated = FALSE;  // generated data not set yet
}

int Data::genData() const
{
    if (!generated)
    {
         // perform time consuming calculation that you only want to
         // do if required, and then only once!
         cerr << "Generating extra data" << endl;

         // since genData is const we HAVE to do something ...
         Data *self((Data *) this);       // self is not const anymore :-)

         self->gData = data+1;
         self->generated=TRUE;
    }
    return gData;
}

void main()
{
    const Data data(3);

    cout << data.getData() << endl;
    cout << data.getGenData() << endl;  // generates the genData
    cout << data.getGenData() << endl;  // uses cached genData
}

/*
output:

3
Generating extra data
4
4
*/

-- marc.

##########################################################################
  preferred address = marc@offline.be
  e-mail marc@offline.be marc@offline.UUCP offline!marc ub4b!offline!marc
  bix    mduponcheel mduponcheel@BIX.com
  fido   2:292/603.26 Marc.Duponcheel@p26.f603.n292.z2.FidoNet.Org
##########################################################################




Author: adk@Warren.MENTORG.COM (Ajay Kamdar)
Date: 2 Apr 1993 17:54:37 -0500
Raw View
In article <1pgr7c$lf5@minotaur.cssc-syd.tansu.com.au> gregw@cssc-syd.tansu.com.au (Greg Wilkins) writes:
>
>I have a problem with const.  Currently, when an object is const -
>absolutely none of its members may be modified, or non-const member
>functions called.  To me, is too strict an overides the OO concept of

A ~const proposal is under consideration by the C++ standardization
committee. The proposal would permit objects to be meaningwise const
without being bitwise const.

I believe the extensions working group has already approved this proposal.


- Ajay

--
I speak for no one but myself.

Ajay Kamdar                               Email : ajay_kamdar@mentorg.com
Mentor Graphics, IC Group (Warren, NJ)    Phone : (908) 604-0842




Author: bs@alice.att.com (Bjarne Stroustrup)
Date: 6 Apr 93 11:33:49 GMT
Raw View

adk@Warren.MENTORG.COM (Ajay Kamdar @ Mentor Graphics Corp. -- IC Group) writes

 > A ~const proposal is under consideration by the C++ standardization
 > committee. The proposal would permit objects to be meaningwise const
 > without being bitwise const.
 >
 > I believe the extensions working group has already approved this proposal.

It has been extensively discussed, but nothing has been approved (or rejected)
so far. Building consensus on a topic like this takes more time than one would
think.

 - Bjarne




Author: dic5340@hertz.njit.edu (David Charlap)
Date: 8 Apr 93 20:47:02 GMT
Raw View
In article <1pgr7c$lf5@minotaur.cssc-syd.tansu.com.au> gregw@cssc-syd.tansu.com.au (Greg Wilkins) writes:

>I have a problem with const.  Currently, when an object is const -
>absolutely none of its members may be modified, or non-const member
>functions called.  To me, is too strict an overides the OO concept of
>separating interface from implementation. What const should prevent you
>from doing is modifying members that represent the Value(big V) of the
>object, but should not prevent you from modifying the value(little v)
>of members used for implementation.

The problem is in what a useful syntax should be, not in deciding
whether or not to implement the sematics.  Personally, I think a
logical way would be for members to be const as seen by external code,
but not from within the object itself, unless the members are
explicitly declared const.  So... If an object is declared const, the
object can still update it's own members, but no outside procedure
(that may have allocated the instance) will be able to write to public
members.  I'm not sure how protected members would behave, here,
though.

This probably couldn't be implemented, though, since it would render
existing code incompatible.  The main advantage is that it doesn't
require a new keyword.
--
David Charlap          | "Listen computer, if you don't do as I say,
dic5340@hertz.njit.edu |  I'm going straight to your main memory banks
-----------------------+  with a large axe to give you a reprogramming
                          you'll never forget!"




Author: hendrik@vedge.com (Hendrik Boom)
Date: 8 Apr 93 13:00:03 GMT
Raw View
: gregw@cssc-syd.tansu.com.au (Greg Wilkins) writes:
:
:
: >I have a problem with const.  Currently, when an object is const -
: >absolutely none of its members may be modified, or non-const member
: >functions called.  To me, is too strict an overides the OO concept of
: >separating interface from implementation. What const should prevent you
: >from doing is modifying members that represent the Value(big V) of the
: >object, but should not prevent you from modifying the value(little v)
: >of members used for implementation.

Could get around it via indirection: let your const object contain a
pointer (or reference) to a nonconst object.

Unfortunately, this gives you two objects when you wanted one.
--
-------------------------------------------------------
Try one or more of the following addresses to reply.
at work: hendrik@vedge.com,  iros1!vedge!hendrik
at home: uunet!ozrout!topoi!hendrik