Topic: Compile-time vs. Run-time constant objects


Author: "Bradd W. Szonye" <bradds@concentric.net>
Date: 1997/09/20
Raw View
Cristian Georgescu <Cristian.Georgescu@worldnet.att.net> wrote in article
<01bcbf52$6855acc0$183274cf@worldnet.worldnet.att.net>...
>
> [Why these restrictions on aggregates?]
>
> - Why no  user-declared constructors? (If you use initialisation list,
the
> constructors should no be invoked; rather, a memberwise initialisation
> should be done.)

Because users of the class could use them to break encapsulation,
potentially violating class invariants. If a user-defined constructor
exists, presumably there's more to the class than a simple data layout.
(This isn't always true, but the compiler can't tell the difference without
"hints" that aren't in the language.) A particular compiler, of course,
could change this with a #pragma aggregate(class_name) or something
similar.

> - Why no private or protected non-static data members?

Because now class users who write an aggregate initializer are almost
certainly breaking encapsulation.

> - Why no base classes? (if thay are aggregates also?)

Because the committe would then need to define what order to list base
classes in the aggregate initializer-list, especially virtual base classes.
That's not a huge undertaking, but it's one more feature to delay the
standard's release.

> - Why no virtual functions? (the vptr table can be stored in ROM also?)

Because the object is then no longer C-compatible, and doesn't need a
C-compatible initialization syntax (as Steve Clamage explains in his
article). There probably are no technical problems with allowing this;
however, there is also no need to define it since C++ also allows
user-declared constructors.

> Besides even if you use the aggregate stuff, and initialize the aggregate
> by the initialization list, then there is no guarantee what so ever that
> the storage is achieved at compile time rather that done when the program
> starts execution...!

Besides, even if an object uses a user-defined construct, there's no
guarantee that the compiler WON'T be able to put the thing in read-only
memory. It could, after all, execute some of your code at run-time, if the
compiler can set up "sandboxes" such that the partial execution can't crash
the compiler itself.

For that matter, even if the constructor initializes such things at
run-time, there's no guarantee that it won't also be able to change the
allocated memory to a "read-only segment" after doing so. This of course
won't help embedded-code start-up time, but it can be a good
program-correctness tool.

These things are entirely QOI issues. If you need to reduce embedded
start-up time, then buy (or create) an embedded-code compiler that knows
how to do these things. If you want to make sure that nobody fools with
your declared-const objects, then buy a compiler that knows how to put them
in read-only memory once initialized.

The standard can't very well define these things without also defining
things like read-only memory and all its variants... physical ROM,
operating-system protected memory, and the like. Not all systems provide
these things: a lot don't.
--
Bradd W. Szonye
bradds@concentric.net
http://www.concentric.net/~Bradds
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Steve Clamage <stephen.clamage_nospam@eng.sun.com>
Date: 1997/09/14
Raw View
Cristian Georgescu wrote:
>
> In my experience the aggregate initialization works only for even more
> restrictive cases. But this should be the fault of the compiler.
>
> Even so, I do not see why these restrictions?
>
> - Why no  user-declared constructors? (If you use initialisation list, the
> constructors should no be invoked; rather, a memberwise initialisation
> should be done.)
>
> - Why no private or protected non-static data members?
>
> - Why no base classes? (if thay are aggregates also?)
>
> - Why no virtual functions? (the vptr table can be stored in ROM also?)
>
> Besides even if you use the aggregate stuff, and initialize the aggregate
> by the initialization list, then there is no guarantee what so ever that
> the storage is achieved at compile time rather that done when the program
> starts execution...!

Defining the concepts of aggregate and POD were done for purposes
of defining C compatibility, and had nothing to do with trying
to specify compile-time vs run-time initialization.

The idea is that a C-like object in C++ can be treated the same way
as in C. The same layout guarantees apply, and in particular you
can use C-style aggregate initialization. Once you add features
that affect object layout, like those you list above, the object no
longer looks like anything you can declare in C (any attempt you
make to write a C version of such a class will not be portable),
and C compatibility concerns no longer apply.

C++ does not directly support RAM/ROM distinctions, just as it
does not support any other special-purpose hardware concerns.

--
Steve Clamage, stephen.clamage_nospam@eng.sun.com
( Note: remove "_nospam" when replying )
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net>
Date: 1997/09/17
Raw View
>
> C++ does not directly support RAM/ROM distinctions, just as it
> does not support any other special-purpose hardware concerns.
>

I intended to formulate a more general question.
Let me give am example:

class Example {
public:
 Example(int val) : val2(val) {};

 const int Value1 () const {return 1;}
 const int Value2 () const {return val2;}

 const int Value3 () const {return val3;}

private:
 const int val2;
 static const int val3 = 3;
};

static const int Example::val3;

void
main () {
 Example ex(1);
}

In the above example, the Value1 returns a compile time constant (1 is in
the code, therefore exists before the program starts), whereas the Value2
return a run time variable, which has to be initialized by the constructor
at run time (space is allocated and value is initialized).

The question is if there is a way to control this kind of behaviour for the
variables like val3?

IMO, static constants could be allocated and initialized either at compile
time or at run time. Compile time allocation would produce a larger
executable but the program start-up would be faster. The run time
allocation would produce a smaller executable and the program start-up
would be slower.

This kind of trade-off is very imortant in embedded systems that may need
to be rebooted fast.

--
Cristian Georgescu
_________________________________________________
    Smith Industries
    Aerospace & Defense Systems
    7-9 Vreeland Road,
    Florham Park, NJ 07932, USA.
_________________________________________________
E-mail: Georgescu_Christian@si.com
---
[ 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
]





Author: Gerard Weatherby <gerardw@alum.mit.edu>
Date: 1997/09/11
Raw View
Cristian Georgescu wrote:
> 2) theObjectInROM can be stored in ROM (or alternatively can be considered
> a compile time constant). In this case the storage of the theObjectInROM
> should be achieved at compile time rather than at run time.
>
> The question is:
>
> Does C++ support this type of distinction concerning the storage type?
> ----------------------------------------------------------------------
Yes, for certain classes:

 8.5.1  Aggregates                                      [dcl.init.aggr]

1 An aggregate is an array or a class (_class_)  with  no  user-declared
  constructors  (_class.ctor_),  no private or protected non-static data
  members (_class.access_), no base classes  (_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.
  [Example:
          struct A {
                  int x;
                  struct B {
                          int i;
                          int j;
                  } b;
          } a = { 1, { 2, 3 } };
  initializes a.x with 1, a.b.i with 2, a.b.j with 3.  ]

3 An aggregate that is a class can also be  initialized  with  a  single
  expression not enclosed in braces, as described in _dcl.init_.

4 An  array  of  unknown size initialized with a brace-enclosed initial-
  izer-list containing n initializers, where n  shall  be  greater  than
  zero, is defined as having n elements (_dcl.array_).  [Example:
          int x[] = { 1, 3, 5 };
  declares  and  initializes x as a one-dimensional array that has three
  elements since no size was specified and there are three initializers.
  ]  An  empty  initializer list {} shall not be used as the initializer
  for an array of unknown bound.8)
---
[ comp.std.c++ is moderated.  To submit articles: try just posting with      ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu         ]
[ FAQ:      http://reality.sgi.com/employees/austern_mti/std-c++/faq.html    ]
[ Policy:   http://reality.sgi.com/employees/austern_mti/std-c++/policy.html ]
[ Comments? mailto:std-c++-request@ncar.ucar.edu                             ]





Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1997/09/11
Raw View
Gerard Weatherby wrote:
>
> Cristian Georgescu wrote:
> > 2) theObjectInROM can be stored in ROM (or alternatively can be considered
> > a compile time constant). In this case the storage of the theObjectInROM
> > should be achieved at compile time rather than at run time.
> >
> > The question is:
> >
> > Does C++ support this type of distinction concerning the storage type?
> > ----------------------------------------------------------------------
> Yes, for certain classes:
>
>  8.5.1  Aggregates                                      [dcl.init.aggr]
>
> 1 An aggregate is an array or a class (_class_)  with  no  user-declared
>   constructors  (_class.ctor_),  no private or protected non-static data
>   members (_class.access_), no base classes  (_class.derived_),  and  no
>   virtual functions (_class.virtual_).
>

What about mutable? Objects with mutable members obviously can't be
stored in ROM (except if the mutable members are allowed to be at a
different location than the rest of the object).

[...]
---
[ 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
]





Author: "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net>
Date: 1997/09/12
Raw View
Gerard Weatherby <gerardw@alum.mit.edu> wrote in article
<34175514.106D@alum.mit.edu>...
> Cristian Georgescu wrote:
> > 2) theObjectInROM can be stored in ROM (or alternatively can be
considered
> > a compile time constant). In this case the storage of the
theObjectInROM
> > should be achieved at compile time rather than at run time.
> >
> > The question is:
> >
> > Does C++ support this type of distinction concerning the storage type?
> > ----------------------------------------------------------------------
> Yes, for certain classes:
>
>  8.5.1  Aggregates                                      [dcl.init.aggr]
>
> 1 An aggregate is an array or a class (_class_)  with  no  user-declared
>   constructors  (_class.ctor_),  no private or protected non-static data
>   members (_class.access_), no base classes  (_class.derived_),  and  no
>   virtual functions (_class.virtual_).

In my experience the aggregate initialization works only for even more
restrictive cases. But this should be the fault of the compiler.

Even so, I do not see why these restrictions?

- Why no  user-declared constructors? (If you use initialisation list, the
constructors should no be invoked; rather, a memberwise initialisation
should be done.)

- Why no private or protected non-static data members?

- Why no base classes? (if thay are aggregates also?)

- Why no virtual functions? (the vptr table can be stored in ROM also?)

Besides even if you use the aggregate stuff, and initialize the aggregate
by the initialization list, then there is no guarantee what so ever that
the storage is achieved at compile time rather that done when the program
starts execution...!


--
Cristian Georgescu
_________________________________________________
    Smith Industries
    Aerospace & Defense Systems
    7-9 Vreeland Road,
    Florham Park, NJ 07932, USA.
_________________________________________________
E-mail: Georgescu_Christian@si.com
---
[ 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
]





Author: "Cristian Georgescu" <Cristian.Georgescu@worldnet.att.net>
Date: 1997/09/10
Raw View
In embedded systems it is often useful to put some objects into ROM (Read
Only Memory) rather than in RAM.

---
class CanBeStoredInROM {
 //...
};

class SomeClass {
 //...
 static const CanBeStoredInROM theObjectInROM;
 static const CanBeStoredInROM theObjectInRAM;
 //...
};

// And somewhere goes the definition of the static const theObjectInROM;
// And also somewhere goes the initialisation of the static const
theObjectInROM;

---

It is the philosophy of C++ that objects are constructed via a function
call: the constructor. However in the precedent case it is not clear what
one may want:

1) theObjectInRAM can be built dynamically when the program starts
(allocate space on the stack, initialise, etc). This is to be done via the
constructor call of CanBeStoredInROM after the program starts and befor the
execution enters main().

2) theObjectInROM can be stored in ROM (or alternatively can be considered
a compile time constant). In this case the storage of the theObjectInROM
should be achieved at compile time rather than at run time.

Remark:
-------
In case 1) executable is smaller but start-up time of the program is
longer;
In case 2) executable is bigger but start-up time of the program is
shorter;

The question is:

Does C++ support this type of distinction concerning the storage type?
----------------------------------------------------------------------

IMO, not for the general case. There are some cases as enums (that go in
code section) and (maybe) global constants (but this is at the latitude of
the compiler).

Remark:
-------
Mntioning ROM is not essential: the whole discution is around Compile-time
constant objects vs. Run-time constant objects.

Embedded system compilers go around this problem by providing special
directives as to where specific variables should go: in ROM, RAM, or copied
from ROM into RAM at start-up. However this works only for predefined-types
and for (very!) simple classes. The copy from ROM into RAM at start-up can
be solved by a special copy-constructor from a mirror ROM-able class,
therefore only the distinction ROM vs. RAM really matters.

P.S.
----
I do not want to be misunderstood: C++ already provides a lot for embedded
systems programming. But a finer grain control in this direction would
greatly increase the success of the language in this area. Besides, as I
have remarked, this problem can be posed for in general.

--
Cristian Georgescu
_________________________________________________
    Smith Industries
    Aerospace & Defense Systems
    7-9 Vreeland Road,
    Florham Park, NJ 07932, USA.
_________________________________________________
E-mail: Georgescu_Christian@si.com
Cristian.Georgescu@worldnet.att.net
---
[ 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
]