Topic: Is an empty expression a constant expression?


Author: AllanW <allan_w@my-deja.com>
Date: 1999/10/14
Raw View
Okay, but:

   int q = 5;
   int x = q + 17 - q;

A simple compiler would see the variable q in x's
initialization, and conclude that x has a dynamic
initializer.

An optimizing compiler would recognize that x's
initialization is equivalent to
   int x = 17;
which would normally qualify as static initialization.

Does x have static initialization on optimizing
compilers? Or is it still dynamic despite the
optimization?

--
Allan_W@my-deja.com is a "Spam Magnet," never read.
Please reply in newsgroups only, sorry.


Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1999/10/14
Raw View
In article <7ttn70$i8j$1@nnrp1.deja.com>, allan_w@my-deja.com says...
> Okay, but:
>
>    int q = 5;
>    int x = q + 17 - q;
>
> A simple compiler would see the variable q in x's
> initialization, and conclude that x has a dynamic
> initializer.
>
> An optimizing compiler would recognize that x's
> initialization is equivalent to
>    int x = 17;
> which would normally qualify as static initialization.
>
> Does x have static initialization on optimizing
> compilers? Or is it still dynamic despite the
> optimization?

I think this one should be fairly clear: as long as the abstract
semantics say it's dynamic, it stays dynamic even if optimization can
turn it into something that could be done statically.  IOW,
optimization doesn't change the required semantics of the operation --
it just allows the compiler to meet the requirements in different
ways.

--
    Later,
    Jerry.

The universe is a figment of its own imagination.
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Salters <salters@lucent.com>
Date: 1999/10/14
Raw View
AllanW wrote:

> Okay, but:
>
>    int q = 5;
>    int x = q + 17 - q;

> A simple compiler would see the variable q in x's
> initialization, and conclude that x has a dynamic
> initializer.

> An optimizing compiler would recognize that x's
> initialization is equivalent to
>    int x = 17;
> which would normally qualify as static initialization.

> Does x have static initialization on optimizing
> compilers? Or is it still dynamic despite the
> optimization?

Dynamic, of course. But without a standard, I can't tell if
a diagnostic is required. And there is very little to stop
an optimizing compiler from doing exactly what you describe.

That's the funny thing about undefined behavior and the likes:
it might work (until you show your boss, in which case Murphy
kicks in ;-).

Michiel Salters


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "C. M. Heard/VVNET, Inc." <heard@vvnet.com>
Date: 1999/10/11
Raw View
Francis Glassborow wrote:
>
> In article <380389b6.366056741@news.internetconnect.net>, Pablo Halpern
> <phalpern@newview.org> writes
> >Still, the deletion of the words between CD-2 and the final standard is
> >interesting. Anybody want to file a defect report on this ambiguity?
>
> I think that it is covered by the first DR proposed (by Andy Koenig)

If you mean Issue #35, I don't see that.  The question originally raised
by this thread was whether

X a;

X b(1);

qualify as initializations with constant expressions when X is a non-POD
type.  If so, then the words in the standard (quoted by James Kuyper Jr.)

> "Zero-initialization and initialization with a constant expression are
> collectively called _static initialization_; all other initialization is
> _dynamic initialization_. Objects of POD types (3.9) with static storage
> duration initialized with constant expressions (5.19) shall be
> initialized before any dynamic initialization takes place."

would would be telling us that the above initializations are static
initializations.  That would be strange, since the constructors could
have non-trivial runtime actions embedded within them that one would
normally think of as dynamic, e.g.,

struct X {
  X(void) { cout << "initialized with empty expression" << endl; }
  X(int) { cout << "initialized with integer expression" << endl; }
  ~X() { cout << "destroyed" << endl; }
};

Mike
--
C. M. Heard/VVNET, Inc.
heard@vvnet.com
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: phalpern@newview.org (Pablo Halpern)
Date: 1999/10/09
Raw View
"James Kuyper Jr." <kuyper@wizard.net> wrote:

>
>"C. M. Heard/VVNET, Inc." wrote:
>>
>> Jerry Coffin wrote:
>> >
>> > In section 3.6.2, the standard classifies initialization of objects at
>> > namespace scope into static and dynamic initialization.  Summarizing,
>> > static initialization is either a default zero initialization, or
>> > initialization with a constant expression; initialization with a non-
>>                 ^
>>           of a POD type
>> > constant expression is dynamic initialization.
>>
>> ... at least that's what it said in CD2.
>
>In the final standard, it doesn't. What it says is:
>
>"Zero-initialization and initialization with a constant expression are
>collectively called _static initialization_; all other initialization is
>_dynamic initialization_. Objects of POD types (3.9) with static storage
>duration initialized with constant expressions (5.19) shall be
>initialized before any dynamic initialization takes place."

Strange. I wonder why the made that change.

>Therefore initialization of a non-POD object with a constant expression
>is still static initialization. It just doesn't have some of the same
>timing guarantees that static initialization of a POD object would have.

It actually seems to leave unspecified when non-POD objects with static
intialization are initialized. Only statically-initialized POD objects
and dynamicly-initialized objects are mentioned. I believe the intent
was still that only POD objects can have static initialization and that
static initialization occurs before dynamic initialization. In other
words, only the type of initialization that doesn't involve running C++
code (even if its an empty function) is guaranteed to occur before the
first statement in main().

Still, the deletion of the words between CD-2 and the final standard is
interesting. Anybody want to file a defect report on this ambiguity?

-------------------------------------------------------------
Pablo Halpern                            phalpern@newview.org

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 news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/10/09
Raw View
In article <380389b6.366056741@news.internetconnect.net>, Pablo Halpern
<phalpern@newview.org> writes
>Still, the deletion of the words between CD-2 and the final standard is
>interesting. Anybody want to file a defect report on this ambiguity?

I think that it is covered by the first DR proposed (by Andy Koenig)


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "C. M. Heard/VVNET, Inc." <heard@vvnet.com>
Date: 1999/10/05
Raw View
"James Kuyper Jr." wrote:
>
>"C. M. Heard/VVNET, Inc." wrote:
>>
>> Jerry Coffin wrote:
>> >
>> > In section 3.6.2, the standard classifies initialization of objects at
>> > namespace scope into static and dynamic initialization.  Summarizing,
>> > static initialization is either a default zero initialization, or
>> > initialization with a constant expression; initialization with a non-
>>                 ^
>>           of a POD type
>> > constant expression is dynamic initialization.
>>
>> ... at least that's what it said in CD2.
>
>In the final standard, it doesn't. What it says is:
>
>"Zero-initialization and initialization with a constant expression are
>collectively called _static initialization_; all other initialization is
>_dynamic initialization_. Objects of POD types (3.9) with static storage
>duration initialized with constant expressions (5.19) shall be
>initialized before any dynamic initialization takes place."

Thanks for the correction.

>Therefore initialization of a non-POD object with a constant expression
>is still static initialization. It just doesn't have some of the same
>timing guarantees that static initialization of a POD object would have.

But does the initialization expression with which a non-POD object
is qualify as a constant expression?  Initialization of such an
object involves a call to a constructor, which may have arbitrary
side-effects.  Another way to put this:  if X is a class with a
constructor taking an int parameter, then when one writes

X x(1);

it implies an invocation of X(1).  So isn't the initialization
expression "X(1)" (which presumably is not a constant expression)
rather than "1"?  And getting back to the original poster's question,
if X has a constructor that takes no arguments, then writing

X x;

implies an invocation of X();  so isn't the initialization expression
"X()" (also presumably not a constant expression) rather than the
empty expression?  Are not these declarations semantically equivalent
(modulo possible temporary elimination) to

X x = X(1);

and

X x = X();

respectively?

Mike
--
C. M. Heard/VVNET, Inc.
heard@vvnet.com


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 1999/10/04
Raw View
"C. M. Heard/VVNET, Inc." wrote:
>
> Jerry Coffin wrote:
> >
> > In section 3.6.2, the standard classifies initialization of objects at
> > namespace scope into static and dynamic initialization.  Summarizing,
> > static initialization is either a default zero initialization, or
> > initialization with a constant expression; initialization with a non-
>                 ^
>           of a POD type
> > constant expression is dynamic initialization.
>
> ... at least that's what it said in CD2.

In the final standard, it doesn't. What it says is:

"Zero-initialization and initialization with a constant expression are
collectively called _static initialization_; all other initialization is
_dynamic initialization_. Objects of POD types (3.9) with static storage
duration initialized with constant expressions (5.19) shall be
initialized before any dynamic initialization takes place."

Therefore initialization of a non-POD object with a constant expression
is still static initialization. It just doesn't have some of the same
timing guarantees that static initialization of a POD object would have.


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 1999/10/04
Raw View
Valentin Bonnard wrote:
>
> Jerry Coffin wrote:
>
> > Now, given something like:
> >
> > struct X {
> >         X() { }
> >         ~X() {}
> > };
> >
> > X x;
> >
> > where the object takes NO value for its initialization, is the
> > initialization considered static or dynamic?
>
> It probably doesn't make a lot of difference in this case.
>
> > In case anybody cares, the idea here is to put some code in the ctor
> > and dtor that will be forced to run at startup/shutdown simply because
> > the object exists.
>
> It doesn't portably work as simply as that.
>
> Anyway, if code has to be run to initialise the object,

This particular object is an empty POD with an empty default
constructor, so no code has to be run.

Anyway, conceptually, the constructor is always run, so that doesn't
distinguish static from dynamic initialization to this case. In terms of
actual code produced, zero-initialization of objects with non-static
data members always involves running code to write the 0's to memory.
Initialization with a constant expression normally involves code to read
the value of that expression and do something with it. Initialization of
objects with virtual functions usually involves setting up the vtable
pointer, or whatever equivalent mechanism is used to keep track of the
dynamic type of the object.

> it's dynamic initialisation, by definition of the word
> ``dynamic'' itself.

In the C++ standard, it doesn't necessarily work to analyze the
individual words that make up a standard-defined phrase. If it did, you
could conclude that a "null pointer constant" must be a pointer - you
could even conclude that it's a null pointer, both of which are false.
By definition it's an integer constant, not a pointer constant.

The term "dynamic" by itself isn't defined by the standard; the term
"dynamic initialization" is:
"Zero-initialization and initialization with a constant expression are
collectively called _static initialization_; all other initialization is
_dynamic initialization_."

To me, default initialization seems like a special case of
"initialization with a constant expression", for the the case where the
constant expression is empty. However, I haven't found any words that
clarify that question. It's certainly not the case that an empty
expression qualifies as a constant expression.
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "James Kuyper Jr." <kuyper@wizard.net>
Date: 1999/10/04
Raw View
Valentin Bonnard wrote:
>
> Jerry Coffin wrote:
>
> > Now, given something like:
> >
> > struct X {
> >         X() { }
> >         ~X() {}
> > };
> >
> > X x;
> >
> > where the object takes NO value for its initialization, is the
> > initialization considered static or dynamic?
>
> It probably doesn't make a lot of difference in this case.
>
> > In case anybody cares, the idea here is to put some code in the ctor
> > and dtor that will be forced to run at startup/shutdown simply because
> > the object exists.
>
> It doesn't portably work as simply as that.
>
> Anyway, if code has to be run to initialise the object,

This particular object is an empty POD with an empty default
constructor, so no code has to be run.

Anyway, conceptually, the constructor is always run, so that doesn't
distinguish static from dynamic initialization to this case. In terms of
actual code produced, zero-initialization of objects with non-static
data members always involves running code to write the 0's to memory.
Initialization with a constant expression normally involves code to read
the value of that expression and do something with it. Initialization of
objects with virtual functions usually involves setting up the vtable
pointer, or whatever equivalent mechanism is used to keep track of the
dynamic type of the object.

> it's dynamic initialisation, by definition of the word
> ``dynamic'' itself.

In the C++ standard, it doesn't necessarily work to analyze the
individual words that make up a standard-defined phrase. If it did, you
could conclude that a "null pointer constant" must be a pointer - you
could even conclude that it's a null pointer, both of which are false.
By definition it's an integer constant, not a pointer constant.

The term "dynamic" by itself isn't defined by the standard; the term
"dynamic initialization" is:
"Zero-initialization and initialization with a constant expression are
collectively called _static initialization_; all other initialization is
_dynamic initialization_."

To me, default initialization seems like a special case of
"initialization with a constant expression", for the the case where the
constant expression is empty. However, I haven't found any words that
clarify that question. It's certainly not the case that an empty
expression qualifies as a constant expression.
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Al Stevens" <alstevens@midifitz.com>
Date: 1999/10/04
Raw View
>In case anybody cares, the idea here is to put some code in the ctor
>and dtor that will be forced to run at startup/shutdown simply because
>the object exists.  Unfortunately, if this is considered dynamic
>initialization, the ctor doesn't need to run until the object is
>actually referenced.

I have seen and used the following idiom:

struct App {
  static App* ap;
  App() { ap = this; }
  // ...
};

App* App::xp = 0;

int main()
{
  if (App::ap != 0)  {
    // ..
  }
}

.... in frameworks that require an object of a class derived from the
application class to be instantiated before the program can operate. I
believe MFC does something similar. Don't know how portable that might be,
but it's always worked.
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "C. M. Heard/VVNET, Inc." <heard@vvnet.com>
Date: 1999/10/04
Raw View
Jerry Coffin wrote:
>
> In section 3.6.2, the standard classifies initialization of objects at
> namespace scope into static and dynamic initialization.  Summarizing,
> static initialization is either a default zero initialization, or
> initialization with a constant expression; initialization with a non-
                ^
          of a POD type
> constant expression is dynamic initialization.

... at least that's what it said in CD2.

> Now, given something like:
>
> struct X {
>         X() { }
>         ~X() {}
> };
>
> X x;
>
> where the object takes NO value for its initialization, is the
> initialization considered static or dynamic?  My thinking says it
> _should_ be static, but if the standard requires this, I'm missing
> where it says so.

No, it's dynamic, since X is not a POD type (by virtue of having a
user-declared constructor).

> In case anybody cares, the idea here is to put some code in the ctor
> and dtor that will be forced to run at startup/shutdown simply because
> the object exists.  Unfortunately, if this is considered dynamic
> initialization, the ctor doesn't need to run until the object is
> actually referenced.

No, dynamic initialization is guaranteed to take place before any object
or function in the same translation unit is referenced (at the discretion
of the implementation, it may take place before the first statement of
main).  Moreover, an object whose constructor or destructor has side
effects must not be elimnated even it appears to be unreferenced.  So
the object does not have to be referenced in order for its ctor to run.

As a practical matter, many (if not most) implementations run the ctors
for namespace scope static objects that are in statically linked modules
before the first statement of main;  such implementations defer calling
of ctors until after first reference to the module only for objects that
are in DLLs.  So you can often achieve the result that you want -- albeit
without a guarantee of portablity -- even if you can't ensure that some
object or function in the translation unit is referenced before the point
in time that you want the startup code to run.

Incidentally, I rely on the technique that you wish to employ in order to
build a dabase of SNMP objects at startup time.  In my case I have always
been able to arrange for every object to co-reside with something else
that's guaranteed to be referenced shortly after the start of main, but
the implementation that I use (gcc) happens to call all the ctors before
the first statement of main in any case (at least for all the objects that
are in statically linked translation units).

Mike
--
C. M. Heard/VVNET, Inc.
heard@vvnet.com
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1999/10/01
Raw View
In section 3.6.2, the standard classifies initialization of objects at
namespace scope into static and dynamic initialization.  Summarizing,
static initialization is either a default zero initialization, or
initialization with a constant expression; initialization with a non-
constant expression is dynamic initialization.

Now, given something like:

struct X {
 X() { }
 ~X() {}
};

X x;

where the object takes NO value for its initialization, is the
initialization considered static or dynamic?  My thinking says it
_should_ be static, but if the standard requires this, I'm missing
where it says so.

In case anybody cares, the idea here is to put some code in the ctor
and dtor that will be forced to run at startup/shutdown simply because
the object exists.  Unfortunately, if this is considered dynamic
initialization, the ctor doesn't need to run until the object is
actually referenced.

Of course, one could make it clearly static initialization with
something like:

struct X {
 X(int x=0) {}
 ~X() {}
};


and simply never passing a non-constant expression as the parameter to
the ctor, but this seems rather ugly, at least to me.

For those who decide to look things up, section 3.6.2 covers the
startup and shutdown, and 5.19 is where constant expressions are
defined...

--
    Later,
    Jerry.

The universe is a figment of its own imagination.


[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/10/03
Raw View
Jerry Coffin wrote:

> Now, given something like:
>
> struct X {
>         X() { }
>         ~X() {}
> };
>
> X x;
>
> where the object takes NO value for its initialization, is the
> initialization considered static or dynamic?

It probably doesn't make a lot of difference in this case.

> In case anybody cares, the idea here is to put some code in the ctor
> and dtor that will be forced to run at startup/shutdown simply because
> the object exists.

It doesn't portably work as simply as that.

Anyway, if code has to be run to initialise the object,
it's dynamic initialisation, by definition of the word
``dynamic'' itself.

--

Valentin Bonnard
---
[ 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    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]