Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why only integral const statics inside a class?

12 views
Skip to first unread message

Espen Ruud Schultz

unread,
Apr 17, 2003, 1:44:33 PM4/17/03
to
I have thought about this for a while. And I can not see why only integrals
can be const statics inside a class or a struct. Why not floating point
numbers or character strings?

, Espen

---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std...@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]

Allan W

unread,
Apr 17, 2003, 8:01:20 PM4/17/03
to
def...@nospam.invalid ("Espen Ruud Schultz") wrote in message news:<F3kna.4698$b71....@news4.e.nsc.no>...

> I have thought about this for a while. And I can not see why only integrals
> can be const statics inside a class or a struct. Why not floating point
> numbers or character strings?

I *think* that some compilers handle these very similarly to the
way that they handle enums. As you probably know, enums cannot
be floating point numbers or character strings.

Naturally, you CAN create const static floats or strings... they just
can't be fully defined in the class or struct.

Espen Ruud Schultz

unread,
Apr 18, 2003, 12:59:14 PM4/18/03
to
"Allan W" <all...@my-dejanews.com> wrote in message
news:7f2735a5.03041...@posting.google.com...

| def...@nospam.invalid ("Espen Ruud Schultz") wrote in message
news:<F3kna.4698$b71....@news4.e.nsc.no>...
| > I have thought about this for a while. And I can not see why only
integrals
| > can be const statics inside a class or a struct. Why not floating point
| > numbers or character strings?
|
| I *think* that some compilers handle these very similarly to the
| way that they handle enums. As you probably know, enums cannot
| be floating point numbers or character strings.
|

Well, that could be it, but I don't think so. First it would be stupid to
set a standard from what a compiler does, the compiler should do what the
standard says. And this is probably the case too. Second, you can have two
or more const static itegrals with the same value. Of course, if it was en
enum, the values could easily be merged, but I don't think so either...

|
| Naturally, you CAN create const static floats or strings... they just
| can't be fully defined in the class or struct.
|

The reason for me asking this is releated to the post "namespace inside a
class", where I want to group some values inside a class. Now if I only had
integral values I could easily group them with a struct and set them as
const statics. To easily see my problem, this is what I have:

namespace MySpace {

namespace MyGroup0 {
const int MyInt0 = 0;
const int MyInt1 = 1;
}

namespace MyGroup1 {
const int MyInt0 = 0;
const int MyInt1 = 1;
}

namespace MyGroup2 {
const char MyChar0[] = "string0";
const char MyChar1[] = "string1";
}

class MyClass {
...
};

}

Everybody can see the disadvantage in having the namespace groups outside
the class. I could, however, put the groups inside the class through
structs and setting the values as const statics. And I can too, but only
the integral values, only MyGroup0 and MyGroup1. MyGroup2 have to stay
outside the class because chars can't be const statics inside a struct. And
if one have to stay outside, then there's no reason to put the others
inside. Especially if it's the one group I can't put inside that I want to
keep private, and the others public...

So once again I feel I have been stopped by a rule just becasue it wan't
needed at the time it was created. Unless there is something I have missed.
I valid reason for only allowing integrals to be const statics inside a
struct...?

, Espen

Matthias Hofmann

unread,
Apr 18, 2003, 6:23:33 PM4/18/03
to
> So once again I feel I have been stopped by a rule just becasue it wan't
> needed at the time it was created. Unless there is something I have
missed.
> I valid reason for only allowing integrals to be const statics inside a
> struct...?

Well, that confuses me as it works on my compiler. I use Microsoft Visual
C++ 6.0 and the following code compiles and works fine:

class CBogus
{
public:
CBogus()
{
cout << m_szString << endl;

cout << m_fNumber << endl;
}

private:
static const char* m_szString;
static const float m_fNumber;
};

const char* CBogus::m_szString = "Hello";
const float CBogus::m_fNumber = 0.2f;

int main()
{
CBogus b;

return 0;
}

The only drawback is that I have to define and initialize static members
outside the class, as my compiler does not comply with the standard in that
respect.

But are you sure the standard does not allow const static character strings
or floating point values? If so, then my compiler must be offering some
language extensions.

Regards,

Matthias

Francis Glassborow

unread,
Apr 18, 2003, 11:02:22 PM4/18/03
to
In article <3ea0...@news.nefonline.de>, Matthias Hofmann
<hof...@anvil-soft.com> writes

>But are you sure the standard does not allow const static character strings
>or floating point values? If so, then my compiler must be offering some
>language extensions.

I think you are both misunderstanding. A class can have static members
of any type. However a class definition is composed of declarations.
static members must be defined once only, this is not allowed in the
class for data. The C++ Standard makes a special provision for static
consts of integer types where the value may be provided in class.
However the definition must still be provided elsewhere.

There is little advantage to providing in class initialisation for other
static members of const type.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

Espen Ruud Schultz

unread,
Apr 18, 2003, 11:02:30 PM4/18/03
to
""Matthias Hofmann"" <hof...@anvil-soft.com> wrote in message
news:3ea0...@news.nefonline.de...

Hmm, works on the VC++ 7 compiler too. Actually, I haven't checked the
standard. But when I first encountered this "problem", I asked around, and
I didn't get any indication as to this not being a problem. So I just
assumed that standard said so.

Anyway, this new discovery doesn't make any sence either. Why do all
non-integral const statics have to be initialized outside the struct? The
compiler will most likely not give them any memory space anyway, and instead
just use the values directly.

Can anybody please enlighten me about what the standard really says about
const statics and classes?

Anyway, thanks for the new info. I would say this was a big step in the
right direction, even though it doesn't make sence to do it like this...

, Espen

Matthias Hofmann

unread,
Apr 19, 2003, 4:50:08 PM4/19/03
to
> There is little advantage to providing in class initialisation for other
> static members of const type.

I see. But where's the big advantage of providing in class initialisation
for integral types? Is it the easier syntax, especially when you want to use
the integral type as the size of an array member of the class like:

class CMyClass
{
static const int m_iSize = 16;
int m_array[m_iSize];
};

Espen Ruud Schultz

unread,
Apr 19, 2003, 4:50:11 PM4/19/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:5PrLnsNv...@robinton.demon.co.uk...

| In article <3ea0...@news.nefonline.de>, Matthias Hofmann
| <hof...@anvil-soft.com> writes
| >But are you sure the standard does not allow const static character
strings
| >or floating point values? If so, then my compiler must be offering some
| >language extensions.
|
| I think you are both misunderstanding. A class can have static members
| of any type. However a class definition is composed of declarations.
| static members must be defined once only, this is not allowed in the
| class for data. The C++ Standard makes a special provision for static
| consts of integer types where the value may be provided in class.
| However the definition must still be provided elsewhere.
|

This is not how I see it. A const static of any type do not need any space
in memeory, and so I do not see why integrals should need special treatment.

|
| There is little advantage to providing in class initialisation for other
| static members of const type.
|

The advantage is the same for any type just as it it for integral const
static members - you can combine the declaration and initialization in the
same line, and therby save one line of code for each const static member (
and the code looks a better too ). No one type of const statics should need
any special treatment as their value is set in stone when the program
runs...

, Espen

Espen Ruud Schultz

unread,
Apr 19, 2003, 4:50:15 PM4/19/03
to
""Matthias Hofmann"" <hof...@anvil-soft.com> wrote in message
news:3ea0...@news.nefonline.de...
|
| Well, that confuses me as it works on my compiler. I use Microsoft Visual
| C++ 6.0 and the following code compiles and works fine:
|
| class CBogus
| {
| public:
| CBogus()
| {
| cout << m_szString << endl;
|
| cout << m_fNumber << endl;
| }
|
| private:
| static const char* m_szString;
| static const float m_fNumber;
| };
|
| const char* CBogus::m_szString = "Hello";
| const float CBogus::m_fNumber = 0.2f;
|
| int main()
| {
| CBogus b;
|
| return 0;
| }
|
| The only drawback is that I have to define and initialize static members
| outside the class, as my compiler does not comply with the standard in
that
| respect.
|

This drawback might be too much. At first I though, "outside the class, but
in the same header file, so ok, this can work". But no, it can't be in the
same hader file if more than one part of the program use this file. They
have to be defined once only in the entire program. Even though I have
ifndef'ed the entire file (linker problem). So this means the user of the
class has to do the initialization, and that is not acceptable...

, Espen

Francis Glassborow

unread,
Apr 19, 2003, 8:06:53 PM4/19/03
to
In article <3ea1...@news.nefonline.de>, Matthias Hofmann
<hof...@anvil-soft.com> writes

>> There is little advantage to providing in class initialisation for other
>> static members of const type.
>
>I see. But where's the big advantage of providing in class initialisation
>for integral types? Is it the easier syntax, especially when you want to use
>the integral type as the size of an array member of the class like:
>
>class CMyClass
>{
>static const int m_iSize = 16;
>int m_array[m_iSize];
>};
>
Basically , yes.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Francis Glassborow

unread,
Apr 19, 2003, 8:06:57 PM4/19/03
to
In article <Ibaoa.5100$8g5....@news2.e.nsc.no>, Espen Ruud Schultz
<def...@nospam.invalid> writes

>"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
>news:5PrLnsNv...@robinton.demon.co.uk...
>> In article <3ea0...@news.nefonline.de>, Matthias Hofmann
>> <hof...@anvil-soft.com> writes
>| >But are you sure the standard does not allow const static character
>strings
>| >or floating point values? If so, then my compiler must be offering some
>| >language extensions.
>|
>| I think you are both misunderstanding. A class can have static members
>| of any type. However a class definition is composed of declarations.
>| static members must be defined once only, this is not allowed in the
>| class for data. The C++ Standard makes a special provision for static
>| consts of integer types where the value may be provided in class.
>| However the definition must still be provided elsewhere.
>|
>
>This is not how I see it. A const static of any type do not need any space
>in memeory, and so I do not see why integrals should need special treatment.

Of course it normally needs space. The question is where, in the code
section or in the static memory block. It maybe that sometimes the
compiler can optimise away the storage requirement.

The reason that integrals received special treatment is because they are
often used for such things as array sizes where the static value is used
at compile time.

If all that is needed is to use the value as part of an expression, the
compiler can provide the appropriate space which the linker can fill.

>
>>
>> There is little advantage to providing in class initialisation for other
>> static members of const type.
>>
>
>The advantage is the same for any type just as it it for integral const
>static members - you can combine the declaration and initialization in the
>same line, and therby save one line of code for each const static member (
>and the code looks a better too ). No one type of const statics should need
>any special treatment as their value is set in stone when the program
>runs...

Except that for integer values the compiler needs to be able to handle
such things as:

const int arraysize(10);
mytype aray[arraysize];

Now the compiler must know the value of arraysize, link time is too late
(well a really good linker/compiler combination might manage but it is
surely much easier if the compiler can see what size is required.]

In class context that means the compiler sometimes needs to know the
value of a static const int.

It never needs to know the value of a float.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Espen Ruud Schultz

unread,
Apr 20, 2003, 2:20:00 AM4/20/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:9Yl6CDBX...@robinton.demon.co.uk...

|
| Except that for integer values the compiler needs to be able to handle
| such things as:
|
| const int arraysize(10);
| mytype aray[arraysize];
|
| Now the compiler must know the value of arraysize, link time is too late
| (well a really good linker/compiler combination might manage but it is
| surely much easier if the compiler can see what size is required.]
|
| In class context that means the compiler sometimes needs to know the
| value of a static const int.
|
| It never needs to know the value of a float.
|

Ok, here's an idea: Instead of making rules for the moment. How about
making rules that makes the language versatile and expandable? All I can
see here is that this is limiting the potential of the language.

If someone found the use for initializing a static const integral inside a
class, then who is to say that there will never be a use for initializing a
static const float inside a class, or a character string? And there is
sertainly nothing wrong by doing it. So why the rule? Why the limitation?

You can argue all you want about why static const integrals should be able
to be initialized inside a class. But I haven't seen a single point on why
a static const float shouldn't be...

, Espen

Francis Glassborow

unread,
Apr 20, 2003, 4:06:30 PM4/20/03
to
In article <Wlmoa.5381$b71....@news4.e.nsc.no>, Espen Ruud Schultz
<def...@nospam.invalid> writes

>You can argue all you want about why static const integrals should be able
>to be initialized inside a class. But I haven't seen a single point on why
>a static const float shouldn't be...

Consistency seems fine, but in fact we have nasty problems concerned
with dynamic initialisation so we would be unlikely to be able to
support a general license for in class initialisers for static const
objects. The question is how to specify a clear unambiguous rule for
when it is allowed. We have one that seems to cover the useful cases. Do
you wish to formulate an alternative that covers a wider range? That
would require justification and I do not think consistency will do
because we cannot allow unconstrained in class initialisers.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Edward Diener

unread,
Apr 20, 2003, 5:40:03 PM4/20/03
to
Francis Glassborow wrote:
> In article <Wlmoa.5381$b71....@news4.e.nsc.no>, Espen Ruud Schultz
> <def...@nospam.invalid> writes
>> You can argue all you want about why static const integrals should
>> be able to be initialized inside a class. But I haven't seen a
>> single point on why a static const float shouldn't be...
>
> Consistency seems fine, but in fact we have nasty problems concerned
> with dynamic initialisation so we would be unlikely to be able to
> support a general license for in class initialisers for static const
> objects.

You should explain what the "nasty problems" are, or at least point
programmers to the right document which details these problems.

Francis Glassborow

unread,
Apr 20, 2003, 6:34:28 PM4/20/03
to
In article <78Eoa.34514$4P1.3...@newsread2.prod.itd.earthlink.net>,
Edward Diener <eldi...@earthlink.net> writes

>> Consistency seems fine, but in fact we have nasty problems concerned
>> with dynamic initialisation so we would be unlikely to be able to
>> support a general license for in class initialisers for static const
>> objects.
>
>You should explain what the "nasty problems" are, or at least point
>programmers to the right document which details these problems.

So what does the following mean in class scope:

static udt1 const aval = 3;
static udt2 const bval = aval;

Given that udt1 has a ctor that takes an int and udt2 has a dtor that
takes a udt1.

Or:

static double const afloat = atan2(3, 4);

And yes, I can write rules to disallow such awkward initialisations, but
the point is that I would have to write such rules for very little
profit.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Espen Ruud Schultz

unread,
Apr 20, 2003, 7:44:32 PM4/20/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:y1UpZvAT...@robinton.demon.co.uk

>
> So what does the following mean in class scope:
>
> static udt1 const aval = 3;
> static udt2 const bval = aval;
>
> Given that udt1 has a ctor that takes an int and udt2 has a dtor that
> takes a udt1.
>
> Or:
>
> static double const afloat = atan2(3, 4);
>
> And yes, I can write rules to disallow such awkward initialisations, but
> the point is that I would have to write such rules for very little
> profit.

Maybe you should...:

(class scope)
static const int MyInt = eval( 1, 2 );

....compiled just fine. The outcome, however, was of course wrong.

It is obvious that a static const in a class scope _always_ will be a
"#define" constant ( not sure how to explain it better atm, but you get the
point ). And it is also obvious that a static const int in a class scope
comes with a warning - "Use at own risk!", at least it should. So why not
just add all built in types to the static-const-in-a-class family, and just
give them the same warning? I'm cool with it. You should know what you're
doing anyway. I would gladly give up on "compiler safety" for language
"flexibility". And it seems like static const ints in class scope already
have.

I just find it cumbersome to initialize a list of floating point values
through a looong initializer list. Especially when I know that _static_
_const_ is what I really could need anyway, and is what I would use if this
was outside a class scope...

, Espen

Francis Glassborow

unread,
Apr 21, 2003, 9:06:45 AM4/21/03
to
In article <B9Goa.5621$b71....@news4.e.nsc.no>, Espen Ruud Schultz
<def...@nospam.invalid> writes

>Maybe you should...:
>
>(class scope)
>static const int MyInt = eval( 1, 2 );

Looking at 9.2 para 4 and 9.4.2 para 4 leads me to think that the
compiler should be issuing a diagnostic because (assuming it isn't a
preprocessor macro) eval(1, 2) is not a constant initialiser.


--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Espen Ruud Schultz

unread,
Apr 21, 2003, 9:40:33 AM4/21/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:dqmS+3Aa...@robinton.demon.co.uk

> In article <B9Goa.5621$b71....@news4.e.nsc.no>, Espen Ruud Schultz
> <def...@nospam.invalid> writes
>> Maybe you should...:
>>
>> (class scope)
>> static const int MyInt = eval( 1, 2 );
>
> Looking at 9.2 para 4 and 9.4.2 para 4 leads me to think that the
> compiler should be issuing a diagnostic because (assuming it isn't a
> preprocessor macro) eval(1, 2) is not a constant initialiser.

eval() is a simpel function returning an int. It was kompiled with VC++ 7
( warning level 3 I think ), not like it should mean anything thought, since
I don't think there are any compilers out there that fully complies to the
standard...

, Espen

Allan W

unread,
Apr 21, 2003, 4:53:13 PM4/21/03
to
> | Espen Ruud Schultz wrote

> | > I have thought about this for a while. And I can not see why
> | > only integrals can be const statics inside a class or a struct.
> | > Why not floating point numbers or character strings?

> "Allan W" <all...@my-dejanews.com> wrote


> | I *think* that some compilers handle these very similarly to the
> | way that they handle enums. As you probably know, enums cannot
> | be floating point numbers or character strings.

Espen Ruud Schultz wrote


> Well, that could be it, but I don't think so. First it would be
> stupid to set a standard from what a compiler does, the compiler
> should do what the standard says. And this is probably the case too.

The language C++ was around before the standard. One of the tasks
of the C++ standard (the major one?) was to document existing
practice. When existing practice differed, the standard was supposed
to select one for all to follow.

In this light, perhaps you would like to rephrase your sentiment?

> Second, you can have two or more const static itegrals with the
> same value. Of course, if it was en enum, the values could easily
> be merged, but I don't think so either...

Sorry, but enums can also have the same value -- even the same enum.

class foo {
enum { zero=0, one,
two=2, sqrt_of_4=2, cuberoot_of_8=2,
half_of_four=2, two_times_one=2
};
};

> | Naturally, you CAN create const static floats or strings... they just
> | can't be fully defined in the class or struct.
>
> The reason for me asking this is releated to the post "namespace inside a
> class", where I want to group some values inside a class. Now if I only had
> integral values I could easily group them with a struct and set them as
> const statics.

---

Allan W

unread,
Apr 21, 2003, 4:54:44 PM4/21/03
to
Espen Ruud Schultz wrote

> It is obvious that a static const in a class scope _always_
> will be a "#define" constant ( not sure how to explain it
> better atm, but you get the point ).
I'm not sure I get the point.

Even if I did, that wouldn't be good enough for the standard.
#define is in the precompiler; long before lexical analysis.
Furthermore, we want our constants to be able to evaluate
expressions such as (40+1), which (in the precompiler) would
always be "an expression" rather than "a constant expression."


> And it is also obvious that a static const int in a class
> scope comes with a warning - "Use at own risk!", at least
> it should. So why not just add all built in types to the
> static-const-in-a-class family, and just give them the
> same warning? I'm cool with it.

Okay, time for a quiz. There's only one question, multiple choice.

Question 1. When C++ was standardized, what did the committee
members think about you, Espen Ruud Schultz?

A. The C++ standard was written (and others agreed to be bound by
it) specifically to satisfy you, Espen Ruud Schultz. How tragic
that they came so close, then made some blundering errors -- all
without even consulting you.

B. The C++ standard was written with this in mind: We know who
Espen Ruud Schultz is, and what he would like. We hate him, so
we'll try to drive him crazy: We'll make the whole language just
logical and easy to use, except for this thing about non-integral
constants in classes. Won't he just hate that?!?

C. The C++ standardization committee hadn't even heard of you,
Espen Ruud Schultz, which is why it was NOT written just for you.
A committee of very smart men take time out of their "productive"
work. Not not only are they not paid for this work, but they (or
their companies) pay dearly for the privilige. They use their best
judgement, plus impressions gathered from this newsgroup and
other communication, to try to determine what would be best
for the language as a whole -- including you, Espen Ruud Schultz,
but also for other people and even companies. "Best for the
language" usually means the greatest good for the greatest number
of people. There are specific design goals that guide them in that
general direction. I'm sure that "consistency" is on that list,
but it doesn't overwhelm it -- there are a great many things that
they should do, or should avoid doing. One of them is, avoid code
constructs that tend to cause errors -- this is the opposite of
your "use at own risk!" warning.

D. Whoops! I, Espen Ruud Schultz, am in the wrong newsgroup.

David Abrahams

unread,
Apr 21, 2003, 6:18:28 PM4/21/03
to

===================================== MODERATOR'S COMMENT:
On further consideration, I probably should have rejected that
article for this exactly this reason.


===================================== END OF MODERATOR'S COMMENT
all...@my-dejanews.com (Allan W) writes:

> Okay, time for a quiz. There's only one question, multiple choice.

<snip>

> D. Whoops! I, Espen Ruud Schultz, am in the wrong newsgroup.

He may be off base, but what did he do to deserve this kind of abuse?

--
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Edward Diener

unread,
Apr 22, 2003, 3:33:35 PM4/22/03
to
Francis Glassborow wrote:
> In article <78Eoa.34514$4P1.3...@newsread2.prod.itd.earthlink.net>,
> Edward Diener <eldi...@earthlink.net> writes
>>> Consistency seems fine, but in fact we have nasty problems concerned
>>> with dynamic initialisation so we would be unlikely to be able to
>>> support a general license for in class initialisers for static const
>>> objects.
>>
>> You should explain what the "nasty problems" are, or at least point
>> programmers to the right document which details these problems.
>
> So what does the following mean in class scope:
>
> static udt1 const aval = 3;
> static udt2 const bval = aval;
>
> Given that udt1 has a ctor that takes an int and udt2 has a dtor that
> takes a udt1.
>
> Or:
>
> static double const afloat = atan2(3, 4);
>
> And yes, I can write rules to disallow such awkward initialisations,
> but the point is that I would have to write such rules for very little
> profit.

It seems as if C++ could allow static const variables to be initialized in a
class for all built-in types and not for object types, and that the
expression used to initialize the static const variable would be a constant
expression. I would disallow any calls of functions but would allow such
types as float or double to be initialized as well as enumerated constants.
It does seem as if only integral consts are a bit restrictive. Wit this
expanded allowance, none of your examples above would be rightly allowed.

Espen Ruud Schultz

unread,
Apr 22, 2003, 3:33:56 PM4/22/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:9Yl6CDBX...@robinton.demon.co.uk

>>
>> The advantage is the same for any type just as it it for integral const
>> static members - you can combine the declaration and initialization in
>> the same line, and therby save one line of code for each const static
>> member ( and the code looks a better too ). No one type of const
>> statics should need any special treatment as their value is set in
>> stone when the program runs...
>
> Except that for integer values the compiler needs to be able to handle
> such things as:
>
> const int arraysize(10);
> mytype aray[arraysize];
>
> Now the compiler must know the value of arraysize, link time is too late
> (well a really good linker/compiler combination might manage but it is
> surely much easier if the compiler can see what size is required.]
>
> In class context that means the compiler sometimes needs to know the
> value of a static const int.
>
> It never needs to know the value of a float.
>

I'm gonna finish my thoughts about static const by going back a few posts
and fill inn something I feel I missed here:

You say that the reason for allowing initialization of static const ints in
class scope, is a special case becasue sometimes the compiler needs to know
the value of an int. I'm with you so far, and I agree. And you probably
also doesn't like the idea of initializing _any_ type of consts in class
scope. But it weights against using macros, and it is the better of two
evils, so you agree to this special case of static const ints. I'm even
with you this far. And I agree about the macros, but not the rest. I can't
see the danger in any static const. In fact, I think of static consts just
as a type checked and scope defined macro ( I think, I don't say it is ).

Talking about choosing the better of two evils: I would say initializing a
huge list of floats through the initializer list is one big evil. And I
would choose the lesser evil, static const float, any day over an unreadable
initializer list or a list of macros. Maybe you don't agree about this
thought?

I just find the initializer list cumbersome. It is perfect for a few
consts, but not for a long list of them. Then I would rather go for a list
of macros, and just thinking about that makes my stomach turn...

PS: I'm sorry if it sounds like I'm putting the words in you mouth when I
talk about what you think. I have no idea what you exact thought are about
this, but I would say this is more the general thoguhts people have.

, Espen

Matthias Hofmann

unread,
Apr 22, 2003, 3:34:34 PM4/22/03
to
> Anyway, this new discovery doesn't make any sence either. Why do all
> non-integral const statics have to be initialized outside the struct? The
> compiler will most likely not give them any memory space anyway, and
instead
> just use the values directly.

I don't know what the standard says, but when I initialize the variable in
class, VC++ 6.0 mixes it up with a pure virtual function, obviously bevause
of the similarities between

virtual int f() = 0;

and

const int value = 2;

I know this because the compiler gives me an error message which mentions
something about a virtual function.

> This drawback might be too much. At first I though, "outside the class,
but
> in the same header file, so ok, this can work". But no, it can't be in
the
> same hader file if more than one part of the program use this file. They
> have to be defined once only in the entire program. Even though I have
> ifndef'ed the entire file (linker problem). So this means the user of the
> class has to do the initialization, and that is not acceptable...

What's so bad about defining them in the .cpp file? The user of the class
does not have to do the initialization, like he does not have to do the
implementation either.

Ron Natalie

unread,
Apr 22, 2003, 3:54:22 PM4/22/03
to

""Matthias Hofmann"" <hof...@anvil-soft.com> wrote in message news:3ea5...@news.nefonline.de...

>
> What's so bad about defining them in the .cpp file? The user of the class
> does not have to do the initialization, like he does not have to do the
> implementation either.
>
If you don't have the initializer visible, you don't have a constant expression
which is required by certain operations.

Francis Glassborow

unread,
Apr 22, 2003, 5:36:38 PM4/22/03
to
In article <VYbpa.6002$b71....@news4.e.nsc.no>, Espen Ruud Schultz
<def...@nospam.invalid> writes

>Talking about choosing the better of two evils: I would say initializing a
>huge list of floats through the initializer list is one big evil. And I
>would choose the lesser evil, static const float, any day over an unreadable
>initializer list or a list of macros. Maybe you don't agree about this
>thought?


But I would not do that. I would do what the standard requires and
initialise static consts at the point of definition.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Edward Diener

unread,
Apr 22, 2003, 7:09:25 PM4/22/03
to
"Matthias Hofmann" wrote:
>> This drawback might be too much. At first I though, "outside the
>> class, but in the same header file, so ok, this can work". But no,
>> it can't be in the same hader file if more than one part of the
>> program use this file. They have to be defined once only in the
>> entire program. Even though I have ifndef'ed the entire file
>> (linker problem). So this means the user of the class has to do the
>> initialization, and that is not acceptable...
>
> What's so bad about defining them in the .cpp file? The user of the
> class does not have to do the initialization, like he does not have
> to do the implementation either.

By initializing them in the class itself, the variable can be used by other
declarations in the class as if one was using a constant value. Thus static
const variables would more closely mimic and replace macro #defines for
values. This can not be done if the static const variable were initialized
in the source file instead.

Allan W

unread,
Apr 22, 2003, 8:34:36 PM4/22/03
to
Espen Ruud Schultz wrote

> So why not just add all built in types to the
> static-const-in-a-class family, and just give them the
> same warning? I'm cool with it.

da...@boost-consulting.com (David Abrahams) wrote


> all...@my-dejanews.com (Allan W) writes:
>
> > Okay, time for a quiz. There's only one question, multiple choice.
>
> <snip>
>
> > D. Whoops! I, Espen Ruud Schultz, am in the wrong newsgroup.
>
> He may be off base, but what did he do to deserve this kind of abuse?

> ===================================== MODERATOR'S COMMENT:
> On further consideration, I probably should have rejected that
> article for this exactly this reason.
> ===================================== END OF MODERATOR'S COMMENT

I didn't intend this as "abuse" and I sincerely apologize if it came
out that way.

This is a standards newsgroup. People have given him good reasons
why a certain part of the standard works the way it does. His reply
was, in effect, "we should have changed it anyway. There would have
been consequences, but I'm cool with it."

As I pointed out in a part of my reply that you snipped, the standard
isn't about making things "cool" just for one person. The whole point
of a standard is a stationary target. If a vendor says that his product
complies with the standard, we now have certain minimum expectations of
that product.

Perhaps I didn't say that the best way possible.

Mike Conley

unread,
Apr 23, 2003, 12:35:50 AM4/23/03
to
francis.g...@ntlworld.com (Francis Glassborow) wrote in
news:5PrLnsNv...@robinton.demon.co.uk:

>
> There is little advantage to providing in class initialisation for
> other static members of const type.
>

Brace initializers can only be used when initializing an aggregate, and I
can't think of a more convenient way to initialize an array of const static
integrals.

--
Mike Conley

Francis Glassborow

unread,
Apr 23, 2003, 9:52:31 AM4/23/03
to
In article <Xns9365E59C28E8...@65.24.2.11>, Mike Conley
<conle...@osu.edu> writes

>francis.g...@ntlworld.com (Francis Glassborow) wrote in
>news:5PrLnsNv...@robinton.demon.co.uk:
>
>>
>> There is little advantage to providing in class initialisation for
>> other static members of const type.
>>
>
>Brace initializers can only be used when initializing an aggregate, and I
>can't think of a more convenient way to initialize an array of const static
>integrals.
>
You are missing the point. We do not allow brace initialisers in pure
declarations, only in definitions. Allowing an initialiser in a
declaration that is not a definition is a very special case. That is
what we have with in class initialisers for static const integer
objects.

You brace initialisation is applied in the perfectly normal place, the
single point of definition that every variable including class statics
must have.

Personally I have always disliked in class initialisers and opposed them
when they were proposed. Basically they were introduced because a number
of people did not like the 'hijacking' of enums to provide manifest
constants at class scope.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

cody

unread,
Apr 23, 2003, 9:53:02 AM4/23/03
to
> So what does the following mean in class scope:
>
> static udt1 const aval = 3;
> static udt2 const bval = aval;
>
> Given that udt1 has a ctor that takes an int and udt2 has a dtor that
> takes a udt1.
>
> Or:
>
> static double const afloat = atan2(3, 4);
>
> And yes, I can write rules to disallow such awkward initialisations, but
> the point is that I would have to write such rules for very little
> profit.

sure there would be lots of problems when you would use non-primitive
datatypes or use other initializers than just compiletime expressions.

i do not see any difference between

const static int i = 0;

and

const static float f = 0.0f;

both are stored in the code, not in the data segment, both are compiletime
expressions, both primitive datatypes.

quesition:
what would be if i compiled the cpp with a value of the const static int i
set to 0, then throw away the cpp file and link only the .obj file to the
project and include the .h file with a const static int i set to 1? the code
in the class itself would still use 0 but outside the class the compiler
would use the new value(1) and there would be no way to detect this kind of
error, wouldnt it?

--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu
[noncommercial and no fucking ads]

James Kanze

unread,
Apr 23, 2003, 9:53:19 AM4/23/03
to
all...@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.03042...@posting.google.com>...

> > | Espen Ruud Schultz wrote
> > | > I have thought about this for a while. And I can not see why
> > | > only integrals can be const statics inside a class or a struct.
> > | > Why not floating point numbers or character strings?

> "Allan W" <all...@my-dejanews.com> wrote
> > | I *think* that some compilers handle these very similarly to the
> > | way that they handle enums. As you probably know, enums cannot be
> > | floating point numbers or character strings.

> Espen Ruud Schultz wrote
> > Well, that could be it, but I don't think so. First it would be
> > stupid to set a standard from what a compiler does, the compiler
> > should do what the standard says. And this is probably the case
> > too.

> The language C++ was around before the standard. One of the tasks of
> the C++ standard (the major one?) was to document existing
> practice. When existing practice differed, the standard was supposed
> to select one for all to follow.

> In this light, perhaps you would like to rephrase your sentiment?

Given the presence of two-phase lookup, export and member templates,
new-style casts, RTTI, for-scope, the STL, std::locale, templated
iostream's, etc., none of which existed before the standard defined it,
perhaps you would care to rephrase YOUR sentiment. A language called
C++ was around before the standard, and is still around today to a large
extent, but this language bears only a passing resemblance to standard
C++. Your statement corresponds to what a standard SHOULD do (IMHO),
but not to what the C++ standard actually did.

That said, the question is valid. It was even considered by the
standards committee. In the end:

- Existing practice didn't allow any initializers in the class
definition. This was awkward because it didn't allow things like:

struct A
{
static size_t const size ;
int data[ size ] ;
} ;

Presumably, the committee could have required making this work. It
probably wouldn't have been much more difficult than export for the
compiler implementors.

The general consensus was that there is no point in adopting
something that can't, or won't be implemented.

- The obvious solution is to allow the initializer in the class
definition. However, things like:

struct A
{
static MyClass const a( "a string", aDouble, anIntFunction() ) ;
} ;

cause problèmes with regards to the order of implementation. It is,
I hope, evident that some restrictions are necessary.

- Given that some restrictions are necessary, the question is: what?
To make things simple, it is preferable that the restrictions are
already formulated in the standard, for other reasons. Given that
the motivation requires supporting constant integral exceptions for
integral types, as a minimum, and what I've just said excludes
dynamic initialization, as a maximum, there aren't that many
choices: restrict it to constant integral expressions, or allow any
static initialization. Between the two, the choice is really pretty
arbitrary. We've given up orthogonality already (since we don't
allow just any initialization). This feature was added fairly late
in the process, and there was doubtlessly some worry about its
effects (especially with regards to floating point). This leads to
favoring a minimalist approach, which was what was adopted.

Don't forget: if once the feature is actually implemented and used, it
turns out that allowing more would be nice, and pose no problems, it is
easy to do. Whereas if you allow a lot, and it later turns out that
allowing it does cause problems, you really can't go back and take it
out. For the moment, I've yet to see any real arguments to the effect
that we need support for floating point, but if someone does present
some, there would be no problem adding it in the future; adding it can't
break any existing code. Where as if we had allowed floating point, and
experience showed that there were problems with it (which, from what I
know about floating point seems likely), it would be impossible to take
it out.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

Victor Bazarov

unread,
Apr 23, 2003, 12:37:33 PM4/23/03
to
"cody" <deutr...@web.de> wrote...
> [...]

> quesition:
> what would be if i compiled the cpp with a value of the const static int i
> set to 0, then throw away the cpp file and link only the .obj file to the
> project and include the .h file with a const static int i set to 1? the
code
> in the class itself would still use 0 but outside the class the compiler
> would use the new value(1) and there would be no way to detect this kind
of
> error, wouldnt it?

Of course there wouldn't. The Standard does not define '.obj'
file or the process of linking.

What if I defined a class, compiled a unit using it, then changed
the class, compiled another unit with a new class, and then passed
objects of that class between the units? It's undefined. There
is no way to specify the outcome of such compilation process.

When you change the source code (no matter how), you're compiling
a different class. It doesn't matter that the layout didn't change
and it's only a static const integer that got a different value.
You managed to have two definitions for the "same" class in your
program. You violated the "one definition rule". Plain and simple.


Victor
--
Please remove capital A's from my address when replying by mail

Espen Ruud Schultz

unread,
Apr 23, 2003, 1:37:50 PM4/23/03
to
"Allan W" <all...@my-dejanews.com> wrote in message
news:7f2735a5.0304...@posting.google.com

>
> This is a standards newsgroup. People have given him good reasons
> why a certain part of the standard works the way it does. His reply
> was, in effect, "we should have changed it anyway. There would have
> been consequences, but I'm cool with it."
>

You didn't read my part where I said that's exactly how it is with static
const integers did you? Because, as proven, static const int is error
prone, but the standard says it's there, so people just have to be "cool"
with it to use it. Wouldn't be any different with floats or chars either -
if they were allowed...

Integers, floating point, and character strings are all relatively the same
when it comes down to this. So in a very childish way I could say: Since
we have static const ints, then why not floats and chars? In some cases
they would make life easier, just as static const ints makes life easier
now. Of course they will "work against" what people think about
initializing anything in class scope, but the ints are already far down that
alley. So why not just send floats and chars to join the ints? I know it
will make my life easier...

, Espen

Mike Conley

unread,
Apr 23, 2003, 1:57:11 PM4/23/03
to
> You brace initialisation is applied in the perfectly normal place, the
> single point of definition that every variable including class statics
> must have.

The perfectly normal place for a member array of const static things is at
the point of declaration. There is no other place where such an
initializer could go.



> Personally I have always disliked in class initialisers and opposed
> them when they were proposed. Basically they were introduced because a
> number of people did not like the 'hijacking' of enums to provide
> manifest constants at class scope.

It seems reasonable to allow them for const static members of any type, if
only because there's no better place to initialize such members.


--
Mike Conley

Matthias Hofmann

unread,
Apr 23, 2003, 2:10:40 PM4/23/03
to

"Edward Diener" <eldi...@earthlink.net> schrieb in im Newsbeitrag:
OUipa.37451$4P1.3...@newsread2.prod.itd.earthlink.net...

> "Matthias Hofmann" wrote:
> By initializing them in the class itself, the variable can be used by
other
> declarations in the class as if one was using a constant value. Thus
static
> const variables would more closely mimic and replace macro #defines for
> values. This can not be done if the static const variable were initialized
> in the source file instead.

So this means that the compiler's "reaction" on the static const variable
can be one of the following two:

1. If the initializer is visible because the variable is initialized in the
class itself, the compiler will optimize the code by putting the constant in
the code segment

2. If the static const is initialized in the cpp file, the compiler will put
this variable in the data segment, and whenever it is used in the code, its
value will have to be looked up in the data segment

Am I getting this right?

Mike Conley

unread,
Apr 23, 2003, 2:10:40 PM4/23/03
to
conle...@osu.edu (Mike Conley) wrote in
news:Xns93668BEE0C50...@65.24.2.11:

> It seems reasonable to allow them for const static members of any
> type, if only because there's no better place to initialize such
> members.
>

That should read any POD type. We wouldn't want any functions called,
including ctors.

Mike Conley

unread,
Apr 23, 2003, 2:26:15 PM4/23/03
to

Never mind. I reread the relevant section. The static's definition
belongs at namespace scope (which kind of makes in class initialization
silly).

Francis Glassborow

unread,
Apr 23, 2003, 2:33:11 PM4/23/03
to
In article <Xns93668BEE0C50...@65.24.2.11>, Mike Conley
<conle...@osu.edu> writes

>> You brace initialisation is applied in the perfectly normal place, the
>> single point of definition that every variable including class statics
>> must have.
>
>The perfectly normal place for a member array of const static things is at
>the point of declaration. There is no other place where such an
>initializer could go.


Please explain because this makes no sense to me.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Francis Glassborow

unread,
Apr 23, 2003, 2:33:51 PM4/23/03
to
In article <3ea6d65c$1...@news.nefonline.de>, Matthias Hofmann
<hof...@anvil-soft.com> writes

>So this means that the compiler's "reaction" on the static const variable
>can be one of the following two:
>
>1. If the initializer is visible because the variable is initialized in the
>class itself, the compiler will optimize the code by putting the constant in
>the code segment
>
>2. If the static const is initialized in the cpp file, the compiler will put
>this variable in the data segment, and whenever it is used in the code, its
>value will have to be looked up in the data segment
>
>Am I getting this right?

No because linkers already do far more complicated things. There is no
reason that a half way decent linker cannot patch up consts. What it
cannot do so easily is cope with static arrays whose size is provided by
a const int.

--
ACCU Spring Conference 2003 April 2-5
The Conference you should not have missed
ACCU Spring Conference 2004 Late April
Francis Glassborow ACCU

---

Mike Conley

unread,
Apr 23, 2003, 10:17:54 PM4/23/03
to
francis.g...@ntlworld.com (Francis Glassborow) wrote in
news:GpRkOWCD...@robinton.demon.co.uk:

> Please explain because this makes no sense to me.

As it shouldn't. It makes no sense because I misunderstood the standard.
Somehow I had gotten the impression that static const members had to be
initialized at the point of declaration (within the class). Clearly, that
is not the case.


--
Mike Conley

Balog Pal

unread,
Apr 23, 2003, 10:18:17 PM4/23/03
to
"James Kanze" <ka...@gabi-soft.de> wrote in message news:d6651fb6.03042...@posting.google.com...

> struct A
> {
> static MyClass const a( "a string", aDouble, anIntFunction() ) ;
> } ;
>
> cause problèmes with regards to the order of implementation. It is,
> I hope, evident that some restrictions are necessary.

What problems and why restrictions?

I had the impression the problem came from the linkers used then. The C linker had PUBDEF and EXTDEF fields for external and publicizes symbols. That was enough for long.
Then some features, like inline required COMDEFs. IIRC first times only functions were used that way, but once the linker had comdef support, it started to spread to other items.

MS has extension in form __declspec( selectany ). It does exactly the same as inlines (and templates).
I just fail to see any difference between common 'object module code' resulting function or object definitions. And C++ already has the one definition rule, so the common definitions will either all match (they will, using .h files), or you have UB (likely specified to pick any random candidate).

I'd welcome that selectany in the next standard. It exists for quite a long period, information on problems and cost of implementation can be easily queried.

I'd guess we could even reuse keyword 'inline' instead of inventing new syntax.

Paul

Randy Maddox

unread,
Apr 24, 2003, 2:44:19 PM4/24/03
to
def...@nospam.invalid ("Espen Ruud Schultz") wrote in message news:<K2Apa.6431$b71....@news4.e.nsc.no>...

> "Allan W" <all...@my-dejanews.com> wrote in message
> news:7f2735a5.0304...@posting.google.com
> >
> > This is a standards newsgroup. People have given him good reasons
> > why a certain part of the standard works the way it does. His reply
> > was, in effect, "we should have changed it anyway. There would have
> > been consequences, but I'm cool with it."
> >
>
> You didn't read my part where I said that's exactly how it is with static
> const integers did you? Because, as proven, static const int is error
> prone, but the standard says it's there, so people just have to be "cool"
> with it to use it. Wouldn't be any different with floats or chars either -
> if they were allowed...

Your "proof" re static const int kind of lost me. Perhaps you could
explain that again a bit more clearly?

>
> Integers, floating point, and character strings are all relatively the same
> when it comes down to this. So in a very childish way I could say: Since
> we have static const ints, then why not floats and chars? In some cases
> they would make life easier, just as static const ints makes life easier
> now. Of course they will "work against" what people think about
> initializing anything in class scope, but the ints are already far down that
> alley. So why not just send floats and chars to join the ints? I know it
> will make my life easier...
>
> , Espen
>

Integers, floating point, and character strings are not quite the same
in terms of when they are initialized or where they are stored. A
const integer value, and possibly, depending on the architecture, a
const floating point value, can be a compile time constant whose value
is inserted into the code segment where it is used. Of course, if you
take the address of such a constant, then it will almost certainly
need to be stored in the data segment instead. Pointers into the code
segment are rather frowned upon, and we never write self-modifying
code anymore ...

A character string, like any other array, const or not, requires
storage in the data segment, and is initialized at run time rather
than being a compile time constant. This makes sense since the name
of an array is in effect a pointer to its first element, so whenever
you declare an array you have in effect taken the address of its
storage.

Things that are different cannot always be treated the same. :-)

Randy.

Espen Ruud Schultz

unread,
Apr 24, 2003, 2:44:31 PM4/24/03
to
"Francis Glassborow" <francis.g...@ntlworld.com> wrote in message
news:GJTkmufK...@robinton.demon.co.uk

> In article <VYbpa.6002$b71....@news4.e.nsc.no>, Espen Ruud Schultz
> <def...@nospam.invalid> writes
>> Talking about choosing the better of two evils: I would say
>> initializing a huge list of floats through the initializer list is one
>> big evil. And I would choose the lesser evil, static const float, any
>> day over an unreadable initializer list or a list of macros. Maybe you
>> don't agree about this thought?
>
>
> But I would not do that. I would do what the standard requires and
> initialise static consts at the point of definition.

This is the reason why I keep posting here. It doesn't seem like you
understand what I'm saying. No offence, but I've had to ask myself "What is
he replying to?" on a few of your replies to my posts.

About your reply to this post: So you're saying that you would do what the
standard requires and initialize a static const float at the point of
definition? This is what I ment, and are arguing for, becasue the standard
does not allow this...

, Espen

Victor Bazarov

unread,
Apr 24, 2003, 3:26:04 PM4/24/03
to
"Espen Ruud Schultz" <def...@nospam.invalid> wrote...
> [...] So you're saying that you would do what the

> standard requires and initialize a static const float at the point of
> definition? This is what I ment, and are arguing for, becasue the
standard
> does not allow this...


Forgive me for barging in, but you seem to be confusing the terms
"declaration" and "definition". Static data members in a class
definition are _declared_. The _definition_ for those members
must be placed _outside_ the class [definition], at the _namespace_
level:

class X {
static const float whatever; // declaration
};
...
const float X::whatever; // definition

There is no _definition_ for static data members _inside_ the
class [definition]. Plain and simple. Static integral consts
are allowed to be _initialised_ where they are _declared_. Not
floats, not aggregates, only integrals, and only because they
may be used instead of enums for _declaring_ other things, like
arrays sizes. Had there been no static consts initialised at
a wrong place (at the point of _declaration_), there would be
no confusion and no argument. Everybody would be using enums,
and be happy. No, somebody needed to allow that strange form,
initialisation at the point of _declaration_. Why? Because the
use of enums looked bad. Oh well...

Victor
--
Please remove capital A's from my address when replying by mail

Allan W

unread,
Apr 24, 2003, 4:17:14 PM4/24/03
to
ka...@gabi-soft.de (James Kanze) wrote

> all...@my-dejanews.com (Allan W) wrote in message
> > The language C++ was around before the standard. One of the tasks of
> > the C++ standard (the major one?) was to document existing
> > practice. When existing practice differed, the standard was supposed
> > to select one for all to follow.
>
> > In this light, perhaps you would like to rephrase your sentiment?
>
> Given the presence of two-phase lookup, export and member templates,
> new-style casts, RTTI, for-scope, the STL, std::locale, templated
> iostream's, etc., none of which existed before the standard defined it,
> perhaps you would care to rephrase YOUR sentiment. A language called
> C++ was around before the standard, and is still around today to a large
> extent, but this language bears only a passing resemblance to standard
> C++. Your statement corresponds to what a standard SHOULD do (IMHO),
> but not to what the C++ standard actually did.

Thanks, but no.

Note that I never said this was the committee's only task, just that it
was the major one.

> The general consensus was that there is no point in adopting
> something that can't, or won't be implemented.

That's another biggie.

> Don't forget: if once the feature is actually implemented and used, it
> turns out that allowing more would be nice, and pose no problems, it is
> easy to do. Whereas if you allow a lot, and it later turns out that
> allowing it does cause problems, you really can't go back and take it
> out. For the moment, I've yet to see any real arguments to the effect
> that we need support for floating point, but if someone does present
> some, there would be no problem adding it in the future; adding it can't
> break any existing code. Where as if we had allowed floating point, and
> experience showed that there were problems with it (which, from what I
> know about floating point seems likely), it would be impossible to take
> it out.

This same principle is useful in designing interfaces (for instance,
public class members). This is not a coincidence.

Espen Ruud Schultz

unread,
Apr 24, 2003, 7:06:16 PM4/24/03
to
"Randy Maddox" <rma...@isicns.com> wrote in message
news:8c8b368d.03042...@posting.google.com

> def...@nospam.invalid ("Espen Ruud Schultz") wrote in message
> news:<K2Apa.6431$b71....@news4.e.nsc.no>...
>> "Allan W" <all...@my-dejanews.com> wrote in message
>> news:7f2735a5.0304...@posting.google.com
>>>
>>> This is a standards newsgroup. People have given him good reasons
>>> why a certain part of the standard works the way it does. His reply
>>> was, in effect, "we should have changed it anyway. There would have
>>> been consequences, but I'm cool with it."
>>>
>>
>> You didn't read my part where I said that's exactly how it is with
>> static
>> const integers did you? Because, as proven, static const int is error
>> prone, but the standard says it's there, so people just have to be
>> "cool"
>> with it to use it. Wouldn't be any different with floats or chars
>> either -
>> if they were allowed...
>
> Your "proof" re static const int kind of lost me. Perhaps you could
> explain that again a bit more clearly?
>

Well, as proven in another post under this discussion somewhere; you can
initialize a static const int with a function call. And that was a big
error, because the static const int was 0 no matter what the function
returned...

>>
>> Integers, floating point, and character strings are all relatively the
>> same
>> when it comes down to this. So in a very childish way I could say:
>> Since
>> we have static const ints, then why not floats and chars? In some cases
>> they would make life easier, just as static const ints makes life easier
>> now. Of course they will "work against" what people think about
>> initializing anything in class scope, but the ints are already far down
>> that
>> alley. So why not just send floats and chars to join the ints? I know
>> it
>> will make my life easier...
>>
>

> Integers, floating point, and character strings are not quite the same
> in terms of when they are initialized or where they are stored. A
> const integer value, and possibly, depending on the architecture, a
> const floating point value, can be a compile time constant whose value
> is inserted into the code segment where it is used. Of course, if you
> take the address of such a constant, then it will almost certainly
> need to be stored in the data segment instead. Pointers into the code
> segment are rather frowned upon, and we never write self-modifying
> code anymore ...
>

Actually, look at the code below. I tried it a few days ago just to see.
And guess what? It's just another proof that static const ints are error
prone, and that they are no less error prone than any other type if allowed
in class scope...

struct MyClass {
static const int MyArraySize = 10;
int MyArray[MyArraySize];
} Class;

int main( void ) {
int *MyPnt;
MyPnt = (int*)&Class.MyArraySize;
*MyPnt = 20;
for( int Runner = 0; Runner < Class.MyArraySize; Runner++ ) {
Class.MyArray[ Runner ] = Runner;
}
return 0;
}

>
> A character string, like any other array, const or not, requires
> storage in the data segment, and is initialized at run time rather
> than being a compile time constant. This makes sense since the name
> of an array is in effect a pointer to its first element, so whenever
> you declare an array you have in effect taken the address of its
> storage.
>

Excuse my language, but this is bullshit, a compiler can and will optimize
character strings, const or not, static or not, as the compiler see fit.
And, as static const ints in class scope, my guess is that the compiler
would explicitly optimize a static const char in class scope in the same
manner.

PS: I'm not sure what the standard say about explicitly optimizing. But
running the above code in the VC++ 7 compiler gives strong indications that
this is exactly what's happening...

, Espen

Espen Ruud Schultz

unread,
Apr 24, 2003, 7:34:27 PM4/24/03
to
""Victor Bazarov"" <v.Aba...@attAbi.com> wrote in message
news:vageg0h...@corp.supernews.com

First. When I tried it this way, the linker chocked on me. I posted this
incident in an earlier post, and you can read all about it there.

Second. To make it past the linker I have to alter the code is such a way
that there is now way the compiler can optimize the code. And this is the
very thing I want to achieve with other types in class scope...

, Espen

Oliver Schoenborn

unread,
Apr 24, 2003, 8:58:00 PM4/24/03
to
On Wed, 23 Apr 2003 13:53:19 +0000, James Kanze wrote:

> all...@my-dejanews.com (Allan W) wrote in message
> news:<7f2735a5.03042...@posting.google.com>...
>> > | Espen Ruud Schultz wrote
>> > | > I have thought about this for a while. And I can not see why
>> > | > only integrals can be const statics inside a class or a struct.
>> > | > Why not floating point numbers or character strings?
>
>

> (...good stuff deleted...)


> Don't forget: if once the feature is actually implemented and used, it
> turns out that allowing more would be nice, and pose no problems, it is
> easy to do. Whereas if you allow a lot, and it later turns out that
> allowing it does cause problems, you really can't go back and take it

> out. (...) Where as if we had allowed floating point, and experience


> showed that there were problems with it (which, from what I know about
> floating point seems likely), it would be impossible to take it out.

Thanks James, this is the first really informative post in this whole
thread. That raises the question: I think many people reading this thread
would like to know what this "problems" alluded to by several people
(clearly more experienced than the many) would be... I don't have enough
experience with compilers to know, can anyone expand on that? I think that
a clear statement of what the problem would be, if static const float
in-class initialization were allowed, would really help answer the original
question.

Best,
Oliber

Victor Bazarov

unread,
Apr 25, 2003, 12:03:38 AM4/25/03
to


You're still confused. You think you can follow one rule of the
language without following any other. That's not right. You have
to follow them all. The linker "chocked" on you because you did
probably violate the "one definition rule". Now, if you don't want
to follow the rules, you shouldn't be using a language that imposes
them.

Victor
--
Please remove capital A's from my address when replying by mail

---

Espen Ruud Schultz

unread,
Apr 25, 2003, 2:03:51 PM4/25/03
to
""Victor Bazarov"" <v.Aba...@attAbi.com> wrote in message
news:Rb1qa.630767$S_4.683016@rwcrnsc53

Yeah, that's what I said in the first post about this "problem". The class
where I tried this is linked multiple times with my program. So to make
this work, the user of the class will have to initialize these static
consts, and that is unacceptable. Pluss, that doing it this way will most
sertainly give these static const their own place on the stack and not be
optimized, which is the primary effect I'm after...

, Espen

Allan W

unread,
Apr 25, 2003, 2:04:26 PM4/25/03
to
def...@nospam.invalid ("Espen Ruud Schultz") wrote
> Actually, look at the code below. I tried it a few days ago just to see.
> And guess what? It's just another proof that static const ints are error
> prone, and that they are no less error prone than any other type if allowed
> in class scope...
>
> struct MyClass {
> static const int MyArraySize = 10;
> int MyArray[MyArraySize];
> } Class;
>
> int main( void ) {
> int *MyPnt;

// MyPnt is a pointer to non-const int.

> MyPnt = (int*)&Class.MyArraySize;

MyArraySize is a const int. In order to assign this address to a pointer
you needed to cast it.

> *MyPnt = 20;

Modifying the const int through a pointer to non-const brings on
undefined behavior.

> for( int Runner = 0; Runner < Class.MyArraySize; Runner++ ) {
> Class.MyArray[ Runner ] = Runner;
> }
> return 0;
> }

Not sure what results you're seeing here, but it's irrelevant --
no matter what behaviour you find on any particular platform, it
isn't a "proof" of anything. (Undefined behavior is allowed, by
definition, to behave any way at all -- including what you might
wrongly happen to expect.)

Perhaps you had a point? I'm sorry, but I missed it -- no abuse
intended, I read and re-read it! Please re-post your point without
any example of undefined behavior, and I will reply just as nicely
as I know how.

James Kanze

unread,
Apr 25, 2003, 3:16:57 PM4/25/03
to
pa...@lib.hu ("Balog Pal") wrote in message
news:<3ea7...@andromeda.datanet.hu>...

> "James Kanze" <ka...@gabi-soft.de> wrote in message news:d6651fb6.0304230
> 323.76...@posting.google.com...

> > struct A
> > {
> > static MyClass const a( "a string", aDouble, anIntFunction(
> ) ) ;
> > } ;

> > cause probl mes with regards to the order of implementation. It


> > is, I hope, evident that some restrictions are necessary.

> What problems and why restrictions?

Order of initialization problems, to begin with.

A class definition will typically be repeated many times in the program,
once in each translation unit which uses the class. Unlike static
initialization, dynamic initialization takes place some time after
program start-up. The current rules guarantee that the initialization
will occur before the first use after main of anything in the
translation unit that contains the definition. What does that mean
here?

> I had the impression the problem came from the linkers used then.

I don't know where you got that impression? There is no fundamental
difference between this and, say, a static variable in an inline
function, from the linker point of view. It does require something more
than what typical Unix linkers were capable of twenty years ago. Any
dynamic initialization does, and C++ implementations twenty years ago
used custom pre- or post-linkers to patch in the necessary
initializations.

> The C linker had PUBDEF and EXTDEF fields for external and publicizes
> symbols. That was enough for long. Then some features, like inline
> required COMDEFs. IIRC first times only functions were used that way,

> but once the linker had comdef support, it s tarted to spread to other
> items.

I'm not sure what linker you are talking about? The earliest MS-DOS
linkers used the Intel object format, which has most of the support
needed, although it would take some tricky use of segments to get by
without a pre- or post-linker. Early Unix linkers didn't, however.

Now that I think of it, maybe this is the reason behind the different
strategies adopted for templates early on. Unix implementations had a
prelinker, which could more or less easily be used to generate the
template instantiations, provided the compiler furnished the necessary
information. It would have been possible for an MS-DOS implementation,
however, to forgo such a prelinker. (I don't remember whether Zortech
actually did.) But of course, there was nothing in the linker which
would easily support templates. So they put everything in the
compiler. But I'm just guessing about this.

At any rate, the problem isn't the linker as such; the problem is
deciding where to put the initialization code so that it only gets
executed once, and that uses have some sort of means of ensuring
initialization before use.

> MS has extension in form declspec( selectany ). It does exactly the


> same as inlines (and templates). I just fail to see any difference
> between common 'object module code' resulting function or object
> definitions. And C++ already has the one definition rule, so the
> common definitions will either all match (they will, using .h files),
> or you have UB (likely specified to pick any random candidate).

What you are describing sounds like a Fortran common block (which, of
course, linkers have supported since there was Fortran). I've never
seen a linker which didn't support it, going back to the mid-70's, at
least, but I don't see where it is relevant to dynamic initialization.
(The Intel 8086 systems of 1979 definitly supported it, for example, as
did the Microsoft linker furnished with their C compiler, version 1.0,
in the early 80's.)

> I'd welcome that selectany in the next standard. It exists for quite
> a long period, information on problems and cost of implementation can
> be easily queried.

The standard doesn't impose anything with regards to the implementation.

> I'd guess we could even reuse keyword 'inline' instead of inventing
> new syntax.

I'm not really sure what you are proposing now. Fortran named common
blocks in C++? Let's also add equivalence and arithmetic goto's and
make it really fun.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Randy Maddox

unread,
Apr 25, 2003, 3:19:26 PM4/25/03
to
def...@nospam.invalid ("Espen Ruud Schultz") wrote in message news:<W2_pa.6875$b71.1...@news4.e.nsc.no>...

C++ never prevents you from shooting yourself in the foot if you
really want to. Using a C-style cast to throw away the constness of
Class.MyArraySize and stuff a troublesome value there is undefined
behavior anyway, so whatever happens after that point is your own
lookout.

> >
> > A character string, like any other array, const or not, requires
> > storage in the data segment, and is initialized at run time rather
> > than being a compile time constant. This makes sense since the name
> > of an array is in effect a pointer to its first element, so whenever
> > you declare an array you have in effect taken the address of its
> > storage.
> >
>
> Excuse my language, but this is bullshit, a compiler can and will optimize
> character strings, const or not, static or not, as the compiler see fit.
> And, as static const ints in class scope, my guess is that the compiler
> would explicitly optimize a static const char in class scope in the same
> manner.
>
> PS: I'm not sure what the standard say about explicitly optimizing. But
> running the above code in the VC++ 7 compiler gives strong indications that
> this is exactly what's happening...
>
> , Espen
>
> ---

Not sure what you're disagreeing with here, but if you will take a
look at the generated code, and the dissasembled code of your vendor
supplied runtime startup code, you will see that I am correct about
arrays being stored in the data segment. If you are trying to say
that a character string is not an array, then you are simply mistaken.
And if you are saying that a const int and a const array can both be
stored in the code segment, then you are again simply mistaken.

I'm a bit surprised that the moderators let your rude comment through.
I had thought that the level of discourse in this newsgroup was just
a tad higher than that.

Randy.

James Kanze

unread,
Apr 25, 2003, 3:20:20 PM4/25/03
to
oliver.s...@utoronto.ca ("Oliver Schoenborn") wrote in message
news:<pan.2003.04.24....@utoronto.ca>...

> On Wed, 23 Apr 2003 13:53:19 +0000, James Kanze wrote:

> > all...@my-dejanews.com (Allan W) wrote in message
> > news:<7f2735a5.03042...@posting.google.com>...
> >> > | Espen Ruud Schultz wrote
> >> > | > I have thought about this for a while. And I can not see why
> >> > | > only integrals can be const statics inside a class or a
> >> > | > struct. Why not floating point numbers or character strings?

> > (...good stuff deleted...)
> > Don't forget: if once the feature is actually implemented and used,
> > it turns out that allowing more would be nice, and pose no problems,
> > it is easy to do. Whereas if you allow a lot, and it later turns
> > out that allowing it does cause problems, you really can't go back
> > and take it out. (...) Where as if we had allowed floating point,
> > and experience showed that there were problems with it (which, from
> > what I know about floating point seems likely), it would be
> > impossible to take it out.

> Thanks James, this is the first really informative post in this whole
> thread. That raises the question: I think many people reading this
> thread would like to know what this "problems" alluded to by several
> people (clearly more experienced than the many) would be... I don't
> have enough experience with compilers to know, can anyone expand on
> that? I think that a clear statement of what the problem would be, if
> static const float in-class initialization were allowed, would really
> help answer the original question.

First, of course, any sort of dynamic initialization is likely to cause
problems, for order of initialization reasons, if nothing else. This is
why the standard currently forbids dynamic initialization even of
integral or enum types. This also eliminates any type with a user
defined constructor (e.g. std::string).

Beyond that, most of the problems will only hold for cross compilers.
Regardless of the target and host architectures, a compiler must
implement integral arithmetic such that it will obtain the same results
as that on the target machine. At present, this is NOT required for
floating point. And floating point does have a lot of funny problems.
And the utility of floating point seems somewhat less to me.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Matthias Hofmann

unread,
Apr 25, 2003, 3:22:55 PM4/25/03
to

"Espen Ruud Schultz" <def...@nospam.invalid> schrieb in im Newsbeitrag:
W2_pa.6875$b71.1...@news4.e.nsc.no...

> "Randy Maddox" <rma...@isicns.com> wrote in message
> news:8c8b368d.03042...@posting.google.com
> > def...@nospam.invalid ("Espen Ruud Schultz") wrote in message
> > news:<K2Apa.6431$b71....@news4.e.nsc.no>...
> >> "Allan W" <all...@my-dejanews.com> wrote in message
> >> news:7f2735a5.0304...@posting.google.com
> >>>
> Actually, look at the code below. I tried it a few days ago just to see.
> And guess what? It's just another proof that static const ints are error
> prone, and that they are no less error prone than any other type if
allowed
> in class scope...
>
> struct MyClass {
> static const int MyArraySize = 10;
> int MyArray[MyArraySize];
> } Class;
>
> int main( void ) {
> int *MyPnt;
> MyPnt = (int*)&Class.MyArraySize; // THIS IS NOT RECOMMENDED !!!

> *MyPnt = 20;
> for( int Runner = 0; Runner < Class.MyArraySize; Runner++ ) {
> Class.MyArray[ Runner ] = Runner;
> }
> return 0;
> }

So what is the "error" that occurs when you run the code above? I cannot try
out myself as VC++ 6.0 won't compile it. Anyway, you have cast a pointer to
a const object into a pointer to a non-const object, and this has nothing to
do with being error-prone - if you do something like that, it's simply your
own fault if something goes wrong.

Espen Ruud Schultz

unread,
Apr 25, 2003, 5:03:02 PM4/25/03
to
"Randy Maddox" <rma...@isicns.com> wrote in message
news:8c8b368d.0304...@posting.google.com

> def...@nospam.invalid ("Espen Ruud Schultz") wrote in message
> news:<W2_pa.6875$b71.1...@news4.e.nsc.no>...
>> "Randy Maddox" <rma...@isicns.com> wrote in message
>> news:8c8b368d.03042...@posting.google.com
>>>
>>> Integers, floating point, and character strings are not quite the same
>>> in terms of when they are initialized or where they are stored. A
>>> const integer value, and possibly, depending on the architecture, a
>>> const floating point value, can be a compile time constant whose value
>>> is inserted into the code segment where it is used. Of course, if you
>>> take the address of such a constant, then it will almost certainly
>>> need to be stored in the data segment instead. Pointers into the code
>>> segment are rather frowned upon, and we never write self-modifying
>>> code anymore ...
>>>
>
> C++ never prevents you from shooting yourself in the foot if you
> really want to. Using a C-style cast to throw away the constness of
> Class.MyArraySize and stuff a troublesome value there is undefined
> behavior anyway, so whatever happens after that point is your own
> lookout.
>

I was just trying to point out what actually would happen if you did "take
an address of such a constant". And Allan W is right, it is undifined.
What happened on my system was that I got two versions of one constant. I'm
not even sure how we got this far though, but it seems like we're off the
original topic...

>>>
>>> A character string, like any other array, const or not, requires
>>> storage in the data segment, and is initialized at run time rather
>>> than being a compile time constant. This makes sense since the name
>>> of an array is in effect a pointer to its first element, so whenever
>>> you declare an array you have in effect taken the address of its
>>> storage.
>>>
>>
>> Excuse my language, but this is bullshit, a compiler can and will
>> optimize
>> character strings, const or not, static or not, as the compiler see fit.
>> And, as static const ints in class scope, my guess is that the compiler
>> would explicitly optimize a static const char in class scope in the same
>> manner.
>>
>> PS: I'm not sure what the standard say about explicitly optimizing.
>> But
>> running the above code in the VC++ 7 compiler gives strong indications
>> that
>> this is exactly what's happening...
>>
>

> Not sure what you're disagreeing with here, but if you will take a
> look at the generated code, and the dissasembled code of your vendor
> supplied runtime startup code, you will see that I am correct about
> arrays being stored in the data segment. If you are trying to say
> that a character string is not an array, then you are simply mistaken.
> And if you are saying that a const int and a const array can both be
> stored in the code segment, then you are again simply mistaken.
>

Sorry about that, it seems like you're right. I think I have turned
character string optimizing upside down. It is actually more optimized by
not optimizing it. But this still doesn't make any sence why you brought
this up against static const char.

>
> I'm a bit surprised that the moderators let your rude comment through.
> I had thought that the level of discourse in this newsgroup was just
> a tad higher than that.
>

The comment ( or one word ) might be rude, but it wasn't an attack on your
person. It was my opinion on one of your posts. And the fact that this
topic is more spaghetti than a basic code just make me frustrated. I did,
however, regret using the word bullshit after I posted it...

, Espen

Matthias Hofmann

unread,
Apr 26, 2003, 8:46:52 PM4/26/03
to

"Espen Ruud Schultz" <def...@nospam.invalid> schrieb in im Newsbeitrag:
gZaqa.6982$8g5.1...@news2.e.nsc.no...

> Yeah, that's what I said in the first post about this "problem". The
class
> where I tried this is linked multiple times with my program. So to make
> this work, the user of the class will have to initialize these static
> consts, and that is unacceptable. Pluss, that doing it this way will most
> sertainly give these static const their own place on the stack and not be
> optimized, which is the primary effect I'm after...

I think a static const will almost certainly not be placed on the stack, but
somewhere within the data segment. However, I still don't see why this
should make the programme run slower than if you were allowed to initialize
the variable at the point of declaration (within the class). As other people
have pointed out, a character string is an array that needs to be stored
somewhere, no matter where it is initialized.

I'm really getting curious what kind of application you are writing that
requires such intense an optimazation - are you sure that this is really
necessary in your case? If your programme is running slow, than it would be
interesting to profile it first - your application might be slowed down at a
totally different place in your code.

And if you really insist on the speed, then why don't you just define a
string outside the class, like

const char * const MY_SPEEDY_STRING = "Now it's fast and I am happy!";

Of course the string is now at global scope, but at least it let's you try
out wether it really makes your programme run faster. It wouldn't surprise
me if there were no difference in speed.

Balog Pal

unread,
Apr 27, 2003, 12:31:40 AM4/27/03
to
"James Kanze" <ka...@gabi-soft.de> wrote in message news:d6651fb6.03042...@posting.google.com...

> > > cause probl mes with regards to the order of implementation. It
> > > is, I hope, evident that some restrictions are necessary.
>
> > What problems and why restrictions?
>
> Order of initialization problems, to begin with.

Order is indeed a problem. Serious problem that hits. And one that IMO shall be covered ASAP.
But It is an unrelated issue.

> A class definition will typically be repeated many times in the program,
> once in each translation unit which uses the class. Unlike static
> initialization, dynamic initialization takes place some time after
> program start-up.

That's all very true. But I see see it as a common case, covered by the ODR rule.

The original thread merely asked to define non-int consts inited with compile-time const expressions. There dynamic stuff, and order is irrelevant. I still can't see why int is special over a double there.

For objects initialised at runtime it can be stated, that result must be identical regardless any possible orders, and definitions be identical. (ONE definition really means all definitions shall be identical, isn't it.) IMHO the programmer can avoid the possible problems easily.

> The current rules guarantee that the initialization
> will occur before the first use after main of anything in the
> translation unit that contains the definition. What does that mean
> here?

I see no problem in implementing the order to make the initialisatoion before anythng that follows the object.
But you're right, another thing can contradict the current order rules: that the initialisation happens _after_ anything that is before this object in the translation unit.
But I think is more like a theoretucal problem, and can be covered by ODR.
(If it's not clear what I mean, please just read on. )

> > I had the impression the problem came from the linkers used then.
>
> I don't know where you got that impression? There is no fundamental
> difference between this and, say, a static variable in an inline
> function, from the linker point of view.

Well, I had in mind the situation some 15 years ago. I used mainly MASM and I recall I couldn't use comdat before version 5 or 6. I thought it was the linker's limitation, as emitting such records is trivial. But I could be mistaken even then, and my memory may just fail. ;-)

> I'm not sure what linker you are talking about? The earliest MS-DOS
> linkers used the Intel object format, which has most of the support
> needed, although it would take some tricky use of segments to get by
> without a pre- or post-linker. Early Unix linkers didn't, however.

That's cool. So we have the technology, let's use it for good -- finally.

> At any rate, the problem isn't the linker as such; the problem is
> deciding where to put the initialization code so that it only gets
> executed once, and that uses have some sort of means of ensuring
> initialization before use.

Writing my original post, I had in mind only static init, where this is not a problem at all. The only task is to mute the 'alredy defined in module...' errors.

Dynamic init is not so trivial, but we have the elemetnts to implement that too. The attached init entries must be COMDAT too, and the linker shall discard all but the first one encountered.

To me it looks pretty similar to discarding the superflous entries for the object itself.

> > MS has extension in form declspec( selectany ). It does exactly the
> > same as inlines (and templates). I just fail to see any difference
> > between common 'object module code' resulting function or object
> > definitions. And C++ already has the one definition rule, so the
> > common definitions will either all match (they will, using .h files),
> > or you have UB (likely specified to pick any random candidate).
>
> What you are describing sounds like a Fortran common block (which, of
> course, linkers have supported since there was Fortran). I've never
> seen a linker which didn't support it, going back to the mid-70's, at
> least, but I don't see where it is relevant to dynamic initialization.

And you're right. The original thread was about having class static constants with const initialisers, usable at compile time. I think that could be trivially covered using selectany -- and it shall not be restricted to class material, namespace objects could be handled similarly.
And I see no real problems extending it all the way, as to include the dynamic init too.

> > I'd welcome that selectany in the next standard. It exists for quite
> > a long period, information on problems and cost of implementation can
> > be easily queried.
>
> The standard doesn't impose anything with regards to the implementation.

It's common to hear on proposals "go, and convince some compiler writer to have it as extrension, then we take it seriously". MS has that extension. So it can be implemented, can be used.

> > I'd guess we could even reuse keyword 'inline' instead of inventing
> > new syntax.
>
> I'm not really sure what you are proposing now. Fortran named common
> blocks in C++? Let's also add equivalence and arithmetic goto's and
> make it really fun.

Well, let's see what we have now:

// .h file:
extern Object o; // extern no possible init here
const Object co("foo");
// .cpp file:
Object o("foo");

Using what I propose, we could write:
//.h file
inline Object o("foo");
inline const Object co("foo");

The original version works only because C++ used a trick making const default to static. So using that we'll have a private copy of co in every unit. Hopefully everyone RTFM and do not think their address are unique. Sure, the compiler will just opt away the object it it can.

The inline one is a regular object with external linkage. The whole program will have exactly one. Just similar way we have template functions and inline functions.

It is allowed to see the definition multiple times in a single translation unit. (That is not the case for const int x=1; stuff! )
Certainly the same thing can be used in a class:

class foo
{
inline static const float fPI = 3.14f;
static string s;
};
inline string foo::s("bar"); // Can be in header

Also with templates:
template<int N>
class c
{
inline static int myN = N; // no extra fuss needed
inline static const string myNstring = MakeString(N);
};

Now, James, is it really that idiotic? I hate nonnecessary redundancy in my programs, and all I got from it is bugs and problems. That extern + definition at one place is thing we do, having no other way. But I just see no point why carry that bag for another decade.

You know people still use preprocessor to define constants. For strings, to avoid multiplication, and having no support in a class. And even ints, for #define is benign to be encountered multiple times, and const int s not. Having a few named numbers here, and there it can soon drive you mad. The 'static' way was a band-aid. Now I'd see some real solution.

Paul

Espen Ruud Schultz

unread,
Apr 27, 2003, 1:27:29 PM4/27/03
to
""Matthias Hofmann"" <hof...@anvil-soft.com> wrote in message
news:3eaa...@news.nefonline.de

You have misunderstood completely. Of course speed is important, but
initializing different types of static consts in class scope won't give
anyone speed, it gives me control and an easy code. And that's what I want.
I want the control of using consts in a class instead of macros. I want the
easy code I get from initializing a static const instead of using the
initializer list.

I see the initializer list as a mean for initializing constants that aren't
set, but are given throught the constructor. Or for single, standalone
constants, not for a large list of constants where their values are know at
compile time and will never ever change.

And on top of this, constants in the initializer list can't always be
optimized, so they get a place on the stack. This is especially the case
for static libraries...

, Espen

James Kanze

unread,
Apr 27, 2003, 1:28:36 PM4/27/03
to
pa...@lib.hu ("Balog Pal") writes:

|> "James Kanze" <ka...@gabi-soft.de> wrote in message
|> news:d6651fb6.03042...@posting.google.com...

|> > > > cause probl mes with regards to the order of
|> > > > implementation. It is, I hope, evident that some
|> > > > restrictions are necessary.

|> > > What problems and why restrictions?

|> > Order of initialization problems, to begin with.

|> Order is indeed a problem. Serious problem that hits. And one that
|> IMO shall be covered ASAP. But It is an unrelated issue.

It's not. Once you allow dynamic initialization, you have order of
initialization problems.

|> > A class definition will typically be repeated many times in the
|> > program, once in each translation unit which uses the class.
|> > Unlike static initialization, dynamic initialization takes place
|> > some time after program start-up.

|> That's all very true. But I see see it as a common case, covered
|> by the ODR rule.

|> The original thread merely asked to define non-int consts inited
|> with compile-time const expressions. There dynamic stuff, and
|> order is irrelevant. I still can't see why int is special over a
|> double there.

|> For objects initialised at runtime it can be stated, that result
|> must be identical regardless any possible orders, and definitions
|> be identical. (ONE definition really means all definitions shall
|> be identical, isn't it.) IMHO the programmer can avoid the
|> possible problems easily.

|> > The current rules guarantee that the initialization will occur
|> > before the first use after main of anything in the translation
|> > unit that contains the definition. What does that mean here?

|> I see no problem in implementing the order to make the
|> initialisatoion before anythng that follows the object.

In every compilation unit in which it is included? What do you do in
the case of conflicts?

|> But you're right, another thing can contradict the current order
|> rules: that the initialisation happens _after_ anything that is
|> before this object in the translation unit. But I think is more
|> like a theoretucal problem, and can be covered by ODR. (If it's
|> not clear what I mean, please just read on. )

|> > > I had the impression the problem came from the linkers used
|> > > then.

|> > I don't know where you got that impression? There is no
|> > fundamental difference between this and, say, a static variable
|> > in an inline function, from the linker point of view.

|> Well, I had in mind the situation some 15 years ago. I used
|> mainly MASM and I recall I couldn't use comdat before version 5 or
|> 6. I thought it was the linker's limitation, as emitting such
|> records is trivial. But I could be mistaken even then, and my
|> memory may just fail. ;-)

As I said, I have no idea what you mean by "comdat". The Intel
linker, and the Intel assembler, supported common since at least
1979. Microsoft had a Fortran compiler before they had C, and you
need something along these lines to link Fortran. (I threw out my
manuals for MASM ca. 1983 on my last move. Didn't think I'd be having
any use for them again:-), and they don't have the nostalgy value of
my old 1401 autocoder manuals.)

|> > I'm not sure what linker you are talking about? The earliest
|> > MS-DOS linkers used the Intel object format, which has most of
|> > the support needed, although it would take some tricky use of
|> > segments to get by without a pre- or post-linker. Early Unix
|> > linkers didn't, however.

|> That's cool. So we have the technology, let's use it for good --
|> finally.

|> > At any rate, the problem isn't the linker as such; the problem
|> > is deciding where to put the initialization code so that it only
|> > gets executed once, and that uses have some sort of means of
|> > ensuring initialization before use.

|> Writing my original post, I had in mind only static init, where
|> this is not a problem at all. The only task is to mute the 'alredy
|> defined in module...' errors.

|> Dynamic init is not so trivial, but we have the elemetnts to
|> implement that too. The attached init entries must be COMDAT too,
|> and the linker shall discard all but the first one encountered.

|> To me it looks pretty similar to discarding the superflous entries
|> for the object itself.

The problem isn't generating the code or getting just one version
linked in. The proble is when to call it.

The current rules define order within a compilation unit. And there
must be a single definition, so it is in a specific compilation unit.
Your extension allows the same initialization to be specified in
several compilation units. With perhaps a conflicting order.

It probably isn't a killer problem. But it is an issue which has to
be addressed. Addressing it takes work, even if there were a trivial
solution. And to date, I've yet to see any benefits which would
accrue from such work.

|> > > MS has extension in form declspec( selectany ). It does
|> > > exactly the same as inlines (and templates). I just fail to
|> > > see any difference between common 'object module code'
|> > > resulting function or object definitions. And C++ already has
|> > > the one definition rule, so the common definitions will either
|> > > all match (they will, using .h files), or you have UB (likely
|> > > specified to pick any random candidate).

|> > What you are describing sounds like a Fortran common block
|> > (which, of course, linkers have supported since there was
|> > Fortran). I've never seen a linker which didn't support it,
|> > going back to the mid-70's, at least, but I don't see where it
|> > is relevant to dynamic initialization.

|> And you're right. The original thread was about having class
|> static constants with const initialisers, usable at compile time.
|> I think that could be trivially covered using selectany -- and it
|> shall not be restricted to class material, namespace objects could
|> be handled similarly. And I see no real problems extending it all
|> the way, as to include the dynamic init too.

First, it would be nice if you'd talk about things everyone could
understand. I have no idea what you mean by selectany; it certainly
isn't part of my compiler technology vocabulary. From your
description, I think it works vaguely something like Fortran named
common blocks. In which case, there's nothing new about it.

|> > > I'd welcome that selectany in the next standard. It exists
|> > > for quite a long period, information on problems and cost of
|> > > implementation can be easily queried.

|> > The standard doesn't impose anything with regards to the
|> > implementation.

|> It's common to hear on proposals "go, and convince some compiler
|> writer to have it as extrension, then we take it seriously". MS
|> has that extension. So it can be implemented, can be used.

What extension? MS allows static const floating point to be
initialized in the class?

In this case, I think that most of the worries about implementation
concern cross compilers. And I'm not sure that they are founded. But
to be sure would require quite a bit of analysis -- floating point is
NOT integral.

|> > > I'd guess we could even reuse keyword 'inline' instead of
|> > > inventing new syntax.

|> > I'm not really sure what you are proposing now. Fortran named
|> > common blocks in C++? Let's also add equivalence and arithmetic
|> > goto's and make it really fun.

|> Well, let's see what we have now:

|> // .h file:
|> extern Object o; // extern no possible init here
|> const Object co("foo");
|> // .cpp file:
|> Object o("foo");

|> Using what I propose, we could write:
|> //.h file
|> inline Object o("foo");
|> inline const Object co("foo");

|> The original version works only because C++ used a trick making
|> const default to static. So using that we'll have a private copy
|> of co in every unit. Hopefully everyone RTFM and do not think
|> their address are unique. Sure, the compiler will just opt away
|> the object it it can.

|> The inline one is a regular object with external linkage. The
|> whole program will have exactly one. Just similar way we have
|> template functions and inline functions.

And when does initialization take place?

|> It is allowed to see the definition multiple times in a single
|> translation unit. (That is not the case for const int x=1; stuff!
|> ) Certainly the same thing can be used in a class:

Nobody is denying any of this. The question is mainly one of when
initialization takes place.

--
James Kanze mailto:ka...@gabi-soft.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

Allan W

unread,
Apr 27, 2003, 11:10:19 PM4/27/03
to
> pa...@lib.hu ("Balog Pal") wrote
> > I'd guess we could even reuse keyword 'inline' instead of inventing
> > new syntax.

ka...@gabi-soft.de (James Kanze) wrote


> I'm not really sure what you are proposing now. Fortran named common
> blocks in C++? Let's also add equivalence and arithmetic goto's and
> make it really fun.

I'm sure you weren't serious when you wrote this. Furthermore, I
hardly see a need for Fortran common blocks in C++ -- we already
have superior ways to share data between compilation units.

But think again about arithmetic gotos. We already have functions
like strcmp() that either return negative, positive, or zero to
represent three different results. Currently, if you wish to branch
three ways for the three cases, you either need to call strcmp()
twice, or store the result in a named variable.

int result = strcmp(a,b);
if (result<0) { /* ... */ }
else if (result>0) { /* ... */ }
else { /* ... equal ... */ }

Note that switch() doesn't help, because (in two cases out of 3) we
don't have specific return values -- just signs.

Arithmetic gotos could improve this. With today's optimizing compilers,
I'm not sure if we could improve generated code or not... but we
certainly could improve source code readibility if we were allowed to
write 3-way branches like this.

What would it look like? Obviously the Fortran syntax wouldn't be
helpful as-is, because C++ code doesn't have line numbers.

1. We could use labels:
if (strcmp(a,b)) less_than, equal_to, greater_than;
// Does a "goto" to one of these labels
This might present parser problems, if it isn't immediately obvious
that less_than, equal_to, and greater_than are all "goto" targets.

2. Or maybe just the presence of certain symbols after the if condition:
if (strcmp(a,b)) < { /* ... less-than ... */ }
== { /* ... equal ... */ }
> { /* ... greater-than ... */ }
Although I can imagine problems where people assume they could use,
for instance, != or <= (there is no need for this 'cause existing if()
could create such conditions).

3. Or we could simply expand switch() to allow ranges:
switch (strcmp(a,b)) {
case 0: /* ... equal ... */ break;
case <0: /* ... less-than ... */ break;
case >0: /* ... greater-than ... */ break;
}
I am aware of a workaround for this that works now:
inline int threeway(int value) { return (value<0)?-1 : (value>0)?1 :0; }
// ...
switch (threeway(strcmp(a,b))) {
case 0: /* ... equal ... */ break;
case -1: /* ... less-than ... */ break;
case 1: /* ... greater-than ... */ break;
}
But this is non-obvious and inconvenient.

Francis Glassborow

unread,
Apr 27, 2003, 11:10:37 PM4/27/03
to
In article <8TOqa.7512$b71.1...@news4.e.nsc.no>, Espen Ruud Schultz
<def...@nospam.invalid> writes

>You have misunderstood completely. Of course speed is important, but
>initializing different types of static consts in class scope won't give
>anyone speed, it gives me control and an easy code. And that's what I want.
>I want the control of using consts in a class instead of macros. I want the
>easy code I get from initializing a static const instead of using the
>initializer list.

Please go and find out how class statics are intialised. The initialiser
has nothing to do with it.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Terje Slettebø

unread,
Apr 28, 2003, 8:43:34 AM4/28/03
to
francis.g...@ntlworld.com (Francis Glassborow) wrote in message news:<7TILQ8Dg...@robinton.demon.co.uk>...
>Subject: Re: Why only integral const statics inside a class?
>
> In article <Wlmoa.5381$b71....@news4.e.nsc.no>, Espen Ruud Schultz
> <def...@nospam.invalid> writes
> >You can argue all you want about why static const integrals should be able
> >to be initialized inside a class. But I haven't seen a single point on why
> >a static const float shouldn't be...
>
> Consistency seems fine, but in fact we have nasty problems concerned
> with dynamic initialisation so we would be unlikely to be able to
> support a general license for in class initialisers for static const
> objects. The question is how to specify a clear unambiguous rule for
> when it is allowed. We have one that seems to cover the useful cases. Do
> you wish to formulate an alternative that covers a wider range? That
> would require justification

There are some cases where it could be useful to be able to have
in-class initialisation of non-integral values, they do tend to rely
on another possible extension, though: Template non-type parameters of
floating point, and possibly compound (POD) types. This extension for
template parameters is discussed in "C++ Templates" by
Josuttis/Vandevoorde.

This could allow one to get rid of some cases which now require
macros, or manual code duplication, and I think you'll agree that this
is a good reason. :)

An example is if you have classes like this:

struct A
{
static const double value;
};

A::value=...;

struct B
{
static const double value;
};

B::value=...;

Recognising the duplication, you may want to generate the classes from
a template, but, no, you can't, as you can't pass the floating point
constant as a template parameter, or initialise the static double in
the class. If you could, you could have done this:

template<double v>
struct test
{
static const double value=v;
};

Instead, you now have to do something like the following, to achieve
the same:

#define TEST(name,v)\
struct name\
{\
static const double value;\
}\
\
name::value=v;

This is not an academic issue; I have code just like this, and it
ain't pretty, but that's how it has to be done, if you want to be able
to easily construct new such classes.

An alternative is to pass a _reference_ to a double, which is allowed.
That requires the object to have external linkage, though, so you
still end up with some boilerplate code:

extern const double valueA=...;

typedef test<valueA> testA;

In other words, you can't specify the value at the template
instantiation.

The same goes for allowing passing string literals as template
parameters. Various ways that may be implemented is discussed in "C++
Templates".

The same extensions could also enable new uses for metaprogramming,
such as compile-time computation with floating point values, or string
literals, including string manipulation.

None of this requires dynamic initialisation; it may be specified in
such a way that the data is stored in the data segment.


Regards,

Terje

Espen Ruud Schultz

unread,
Apr 29, 2003, 1:53:03 AM4/29/03
to
"Francis Glassborow" <fra...@robinton.demon.co.uk> wrote in message
news:ygR5MuBJ...@robinton.demon.co.uk

> In article <8TOqa.7512$b71.1...@news4.e.nsc.no>, Espen Ruud Schultz
> <def...@nospam.invalid> writes
>> You have misunderstood completely. Of course speed is important, but
>> initializing different types of static consts in class scope won't give
>> anyone speed, it gives me control and an easy code. And that's what I
>> want. I want the control of using consts in a class instead of macros.
>> I want the easy code I get from initializing a static const instead of
>> using the initializer list.
>
> Please go and find out how class statics are intialised. The initialiser
> has nothing to do with it.

Well of course the initializer list has nothing to do with statics. I'm
talking about that I have to use the initializer list ( or macros ) on const
types becasue I can _not_ use statics. And that I would rather use static
consts instead of the initializer list, or a list of macros...

, Espen

Anthony Williams

unread,
Apr 29, 2003, 1:54:48 AM4/29/03
to
"terjes."@chello.no (Terje Slettebø) writes:
> template<double v>
> struct test
> {
> static const double value=v;
> };
>

> The same extensions could also enable new uses for metaprogramming,


> such as compile-time computation with floating point values, or string
> literals, including string manipulation.
>
> None of this requires dynamic initialisation; it may be specified in
> such a way that the data is stored in the data segment.

Floating point values are not compile-time constants and cannot be, as the
precise behaviour of operations on floating point types is not defined by the
standard. Is test<1.0> the same instantiation as test<1.01> or test<1.0000001>
or test<1.00000000000000000001>? On some platforms these numbers are the same,
on some not. It might be different between the compiler's platform and the
target platform.

As for compile-time computation, what is the result of 1.0000000000000001 *
1.0000000000000001? Is it the same as any of the above?

Allowing compile-time computation with floating point numbers requires that
the compiler can answer these questions. Currently it is possible for the
compiler to store the text representation of floating point constants in the
executable, and generate code for the target platform that converts these to
numbers at runtime. Under such an implementation, the compiler cannot know the
answer to these questions unless it has a complete emulation layer for the
floating point operations on the target system.

String literals are another matter, and are considerably simpler, since the
semantics of operations on string-literals are well-defined.

Anthony
--
Anthony Williams
Senior Software Engineer, Beran Instruments Ltd.
Remove NOSPAM when replying, for timely response.

cody

unread,
Apr 29, 2003, 1:55:20 AM4/29/03
to
> I see the initializer list as a mean for initializing constants that
aren't
> set, but are given throught the constructor. Or for single, standalone
> constants, not for a large list of constants where their values are know
at
> compile time and will never ever change.
>
> And on top of this, constants in the initializer list can't always be
> optimized, so they get a place on the stack. This is especially the case
> for static libraries...

you are confusing const and static const.

const members are initialized in the initializer list in the ctor:

MyClass::MyClass() : myConst(1000) {}

static const are initialized separately:

int MyClass::myConst = 1000;

there is no need for saving them on a stack or the data-segment.

--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu
[noncommercial and no fucking ads]

Francis Glassborow

unread,
Apr 29, 2003, 1:18:51 PM4/29/03
to
In article <JSbra.7836$b71.1...@news4.e.nsc.no>, Espen Ruud Schultz
<def...@nospam.invalid> writes

>Well of course the initializer list has nothing to do with statics. I'm
>talking about that I have to use the initializer list ( or macros ) on const
>types becasue I can _not_ use statics. And that I would rather use static
>consts instead of the initializer list, or a list of macros...

Sorry, but you have completely lost me. Obviously it is a failure in my
imagination because I cannot see how using an initialiser list to
initialise a const member has anything to do with being/not being able
to use a static const.

Nowhere is there a prohibition on using static consts of any type you
like. As class definitions are composed of pure declarations of members
(except for inline member functions defined in class) members must be
defined elsewhere if they are used. This applies just as much to class
statics as to other members. It is at the point of definition that you
have to provide an initialiser for a static const member UNLESS you have
used the special dispensation for static consts of an integer type that
allows an initialiser to be provided in class. In that circumstance you
must NOT intialise the variable at the point of definition.

Now please post a code example to illustrate the point you are trying to
make.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---

cody

unread,
Apr 29, 2003, 1:19:07 PM4/29/03
to
> Floating point values are not compile-time constants and cannot be, as the
> precise behaviour of operations on floating point types is not defined by
the
> standard. Is test<1.0> the same instantiation as test<1.01> or
test<1.0000001>
> or test<1.00000000000000000001>? On some platforms these numbers are the
same,
> on some not. It might be different between the compiler's platform and the
> target platform.

ok would be the reason to disallow floating point expressions as compiletime
expressions. but why generally forbid floating point initializatin constants
in header files?

can i constant like 1.23456789 treated different on different compilers? are
all 1.23456789 binary the same?
internally floating point is based on decimal powers, so 1.23456789 should
be always the same, no matter which compiler was used, shouldn't it?

--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu
[noncommercial and no fucking ads]

---

Bart van Ingen Schenau

unread,
Apr 29, 2003, 1:50:42 PM4/29/03
to
On Tue, 29 Apr 2003 05:53:03 +0000 (UTC), def...@nospam.invalid
("Espen Ruud Schultz") wrote:

>"Francis Glassborow" <fra...@robinton.demon.co.uk> wrote in message
>news:ygR5MuBJ...@robinton.demon.co.uk
>>

>> Please go and find out how class statics are intialised. The initialiser
>> has nothing to do with it.
>
>Well of course the initializer list has nothing to do with statics. I'm
>talking about that I have to use the initializer list ( or macros ) on const
>types becasue I can _not_ use statics. And that I would rather use static
>consts instead of the initializer list, or a list of macros...

Please explain why you can't use this:

// myclass.h
// ...

class Math {
public:
static const float pi;
// ...
};

// end myclass.h

// myclass.cpp
#include "myclass.h"

static const float Math::pi = 3.14;

// end myclass.cpp

>
>, Espen
>
Bart v Ingen Schenau

Francis Glassborow

unread,
Apr 29, 2003, 2:08:06 PM4/29/03
to
In article <C1yra.1$7k7....@news.ecrc.de>, cody <deutr...@web.de>
writes

>can i constant like 1.23456789 treated different on different compilers? are
>all 1.23456789 binary the same?
>internally floating point is based on decimal powers, so 1.23456789 should
>be always the same, no matter which compiler was used, shouldn't it?

No reason that all compilers will produce exactly the same bit pattern.
BTW internally coding is based on powers of two.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---

cody

unread,
Apr 30, 2003, 11:51:02 AM4/30/03
to
> No reason that all compilers will produce exactly the same bit pattern.
> BTW internally coding is based on powers of two.


i thought a floating point number is stored this way:

mantissa * (10 ^ exponent)?

--
cody

Freeware Tools, Games and Humour
http://www.deutronium.de.vu
[noncommercial and no fucking ads]

James Kanze

unread,
Apr 30, 2003, 2:44:46 PM4/30/03
to
> > pa...@lib.hu ("Balog Pal") wrote
> > > I'd guess we could even reuse keyword 'inline' instead of
> > > inventing new syntax.
> ka...@gabi-soft.de (James Kanze) wrote
> > I'm not really sure what you are proposing now. Fortran named
> > common blocks in C++? Let's also add equivalence and arithmetic
> > goto's and make it really fun.

> I'm sure you weren't serious when you wrote this.

I presumed that the irony would have been evident enough even without a
smilye.

> Furthermore, I hardly see a need for Fortran common blocks in C++ --
> we already have superior ways to share data between compilation units.

We have pointer arithmetic. That allows everything you could do with
Fortran common blocks and equivalent. Sort of, at least; Fortran
guaranteed that sizeof( float ) == sizeof( int ), so you were at least
guaranteed correct alignment.

> But think again about arithmetic gotos. We already have functions like
> strcmp() that either return negative, positive, or zero to represent
> three different results. Currently, if you wish to branch three ways
> for the three cases, you either need to call strcmp() twice, or store
> the result in a named variable.

> int result = strcmp(a,b);
> if (result<0) { /* ... */ }
> else if (result>0) { /* ... */ }
> else { /* ... equal ... */ }

> Note that switch() doesn't help, because (in two cases out of 3) we
> don't have specific return values -- just signs.

That's an arithmetic if, not the arithmetic goto that I mentioned.

> Arithmetic gotos could improve this. With today's optimizing
> compilers, I'm not sure if we could improve generated code or
> not... but we certainly could improve source code readibility if we
> were allowed to write 3-way branches like this.

> What would it look like? Obviously the Fortran syntax wouldn't be
> helpful as-is, because C++ code doesn't have line numbers.

Fortran doesn't have line numbers. It has labels, just like C/C++.
With the difference that the syntax for a label was [1-9][0-9]*.

> 1. We could use labels:
> if (strcmp(a,b)) less_than, equal_to, greater_than;
> // Does a "goto" to one of these labels
> This might present parser problems, if it isn't immediately obvious
> that less_than, equal_to, and greater_than are all "goto" targets.

It's not obvious at all. What you have written is already legal C/C++,
with well defined semantics.

> 2. Or maybe just the presence of certain symbols after the if
> condition:
> if (strcmp(a,b)) < { /* ... less-than ... */ }
> == { /* ... equal ... */ }
> > { /* ... greater-than ... */ }

> Although I can imagine problems where people assume they could use,
> for instance, != or <= (there is no need for this 'cause existing if()
> could create such conditions).

This is interesting. At present, there is no way a legal program can
contain a '<' as the first token after the closing ) of the if block.

> 3. Or we could simply expand switch() to allow ranges:
> switch (strcmp(a,b)) {
> case 0: /* ... equal ... */ break;
> case <0: /* ... less-than ... */ break;
> case >0: /* ... greater-than ... */ break;
> }
> I am aware of a workaround for this that works now:

> inline int threeway(int value) { return (value<0)?-1 : (value>0)?1 :0; }
> // ...
> switch (threeway(strcmp(a,b))) {
> case 0: /* ... equal ... */ break;
> case -1: /* ... less-than ... */ break;
> case 1: /* ... greater-than ... */ break;
> }

> But this is non-obvious and inconvenient.

Non-obvious, because it isn't part of the standard. It seems less
non-obvious than a function remove that doesn't remove anything, or a
set that is in fact a balanced tree:-). Or the fact that modulo types
are spelled "unsigned". (Note that Fortran has a standard function with
exactly the semantics of threeway. It's called sign.)

IMHO, if we want to do anything along these lines, we could start by
creating a new replacement for switch. The one time I designed a
language, it had only one conditional statement, select, with two
variants :

select <expr>
{case <relop> <expr>[ , case <relop> <expr>]... ':'
<statement_list> }...
otherwise <statement_list>
end

or

select
{ case <expr>[ ',' case <expr> ]... ':'
<statement_list> }...
otherwise <statement_list>
end

In the first case, the <relop> could be omitted, in which case, it
defaulted to equals. This allowed things like:

Classical switch:

select var
case 0, case 1:
something() ;
case 2:
somethingElse() ;
end

Three way switch:

select var
case > 0: ...
case == 0 : ...
case < 0: ...
end

Chained if's:

select
case a > b : ...
case x < y : ...
otherwise ...
end

and many other variants.

Personally, I don't think switch et al. is important enough in C++ to
bother with correcting it, but if we did, I would envisage something
like the above. Failing that (and I really don't think it worth the
bother), I wouldn't oppose a standard template function sign, with the
semantics:

template< typename T >
int
sign( T op1 , T op2 )
{
return op1 < op2 ? -1 : op2 < op1 : 1 ? 0 ;
}

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

James Kanze

unread,
Apr 30, 2003, 2:45:28 PM4/30/03
to
fra...@robinton.demon.co.uk (Francis Glassborow) wrote in message
news:<kf2MzXBU...@robinton.demon.co.uk>...

> In article <C1yra.1$7k7....@news.ecrc.de>, cody <deutr...@web.de>
> writes
> >can i constant like 1.23456789 treated different on different
> >compilers? are all 1.23456789 binary the same? internally floating
> >point is based on decimal powers, so 1.23456789 should be always the
> >same, no matter which compiler was used, shouldn't it?

> No reason that all compilers will produce exactly the same bit
> pattern. BTW internally coding is based on powers of two.

On some machines. IBM mainframes still use base 16.

And of course, the size of the mantissa field also varies.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Ron Natalie

unread,
Apr 30, 2003, 2:48:57 PM4/30/03
to

""cody"" <deutr...@web.de> wrote in message news:nnNra.1$WE1...@news.ecrc.de...

> > No reason that all compilers will produce exactly the same bit pattern.
> > BTW internally coding is based on powers of two.
>
>
> i thought a floating point number is stored this way:
>
> mantissa * (10 ^ exponent)?
>
You are wrong in most cases. Most machines use a binary format.
The most common of these is one that is compliant with the IEEE
754 Floating Point standard (just about every processor on the
market these days).

The floating point type is divided into a binary mantissa (which has
an implicit 1 leading it that is not stored), a sign bit, and a binary
base2 exponent. The exponent is stored "biased" (that is it's
an unsigned quanitiy where the most negative value is 0).

Simon F Bone

unread,
Apr 30, 2003, 2:49:01 PM4/30/03
to
"cody" <deutr...@web.de> wrote in message
news:nnNra.1$WE1...@news.ecrc.de...
> > No reason that all compilers will produce exactly the same bit pattern.
> > BTW internally coding is based on powers of two.
>
>
> i thought a floating point number is stored this way:
>
> mantissa * (10 ^ exponent)?
>

Nope, at least not usually. I think IBM mainframes might use
powers of ten, but that's because they were mostly targeting
users like banks that wanted currency data processed. It isn't
a good idea to use powers of ten anyway.

You should look online for an article "What every computer
scientist should know about floating-point arithmetic", by David
Goldberg. I think it was published by the ACM.

In essence, powers of two are more accurate.

HTH,

Simon Bone.

Francis Glassborow

unread,
Apr 30, 2003, 3:04:02 PM4/30/03
to
In article <nnNra.1$WE1...@news.ecrc.de>, cody <deutr...@web.de>
writes

>> No reason that all compilers will produce exactly the same bit pattern.
>> BTW internally coding is based on powers of two.
>
>
>i thought a floating point number is stored this way:
>
> mantissa * (10 ^ exponent)?


Actually the representation is implementation defined but I believe that
most implementations use a power of two exponent internally, in fact
doing it otherwise would seem to make internal manipulations harder than
necessary for no real benefits.

--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

---

James Kanze

unread,
May 2, 2003, 10:37:23 AM5/2/03
to
Si...@sfbone.fsnet.co.uk ("Simon F Bone") wrote in message
news:<b8p0fp$89o$1...@news6.svr.pol.co.uk>...

> "cody" <deutr...@web.de> wrote in message
> news:nnNra.1$WE1...@news.ecrc.de...
> > > No reason that all compilers will produce exactly the same bit
> > > pattern. BTW internally coding is based on powers of two.

> > i thought a floating point number is stored this way:

> > mantissa * (10 ^ exponent)?

> Nope, at least not usually. I think IBM mainframes might use powers of
> ten,

Until a couple of years ago, IBM mainframes used powers of 16. (There
is also very good hardware support for BCD, but it typically isn't
accessible from C or C++.) Since then, they support both the
tranditional, base 16 format and IEEE, although I seem to recall that in
our tests at the time, the IEEE format was significantly slower.

> but that's because they were mostly targeting users like banks that
> wanted currency data processed. It isn't a good idea to use powers of
> ten anyway.

> You should look online for an article "What every computer scientist
> should know about floating-point arithmetic", by David Goldberg. I
> think it was published by the ACM.

> In essence, powers of two are more accurate.

In essence, all are 100% accurate for their definition of the
operations:-). The only real problem is that according to their
definition, floating point arithmetic doesn't obey very many of the laws
of real arithmetic -- addition isn't associative, for example.

What has been pretty well established, I think, is that it is easier to
get more accurate results, and above all, to know just how accurate your
results are, with powers of two.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Simon F Bone

unread,
May 2, 2003, 11:42:10 AM5/2/03
to

James Kanze <ka...@gabi-soft.de> wrote in message
news:d6651fb6.03050...@posting.google.com...

> Si...@sfbone.fsnet.co.uk ("Simon F Bone") wrote in message
> news:<b8p0fp$89o$1...@news6.svr.pol.co.uk>...
> > "cody" <deutr...@web.de> wrote in message
> > news:nnNra.1$WE1...@news.ecrc.de...
> > > > No reason that all compilers will produce exactly the same bit
> > > > pattern. BTW internally coding is based on powers of two.
>
> > > i thought a floating point number is stored this way:
>
> > > mantissa * (10 ^ exponent)?
>
> > Nope, at least not usually. I think IBM mainframes might use powers of
> > ten,
>
> Until a couple of years ago, IBM mainframes used powers of 16. (There
> is also very good hardware support for BCD, but it typically isn't
> accessible from C or C++.) Since then, they support both the
> tranditional, base 16 format and IEEE, although I seem to recall that in
> our tests at the time, the IEEE format was significantly slower.
>

Yeah, I was getting mixed up thinking of BCD support.
Sorry for any confusion.

> > but that's because they were mostly targeting users like banks that
> > wanted currency data processed. It isn't a good idea to use powers of
> > ten anyway.
>
> > You should look online for an article "What every computer scientist
> > should know about floating-point arithmetic", by David Goldberg. I
> > think it was published by the ACM.
>
> > In essence, powers of two are more accurate.
>
> In essence, all are 100% accurate for their definition of the
> operations:-). The only real problem is that according to their
> definition, floating point arithmetic doesn't obey very many of the laws
> of real arithmetic -- addition isn't associative, for example.
>
> What has been pretty well established, I think, is that it is easier to
> get more accurate results, and above all, to know just how accurate your
> results are, with powers of two.
>

Well, I think (in essence ;-)) that how accurate you *know* your results
are is what deterimines their accuracy...

Anyway, there is little point in my trying to pretend to be an expert on
this. The
paper I referred to says it all far better than I could.

Simon Bone

Allan W

unread,
May 2, 2003, 1:48:14 PM5/2/03
to
> ka...@gabi-soft.de (James Kanze) wrote
> > > I'm not really sure what you are proposing now. Fortran named
> > > common blocks in C++? Let's also add equivalence and arithmetic
> > > goto's and make it really fun.

> all...@my-dejanews.com (Allan W) wrote


> > I'm sure you weren't serious when you wrote this.

ka...@gabi-soft.de (James Kanze) wrote


> I presumed that the irony would have been evident enough even without a
> smilye.

It was.

> > But think again about arithmetic gotos. We already have functions like
> > strcmp() that either return negative, positive, or zero to represent
> > three different results. Currently, if you wish to branch three ways
> > for the three cases, you either need to call strcmp() twice, or store
> > the result in a named variable.
>
> > int result = strcmp(a,b);
> > if (result<0) { /* ... */ }
> > else if (result>0) { /* ... */ }
> > else { /* ... equal ... */ }
>
> > Note that switch() doesn't help, because (in two cases out of 3) we
> > don't have specific return values -- just signs.
>
> That's an arithmetic if, not the arithmetic goto that I mentioned.

My mistake. It's been a long time since I used Fortran.

> > Arithmetic gotos could improve this. With today's optimizing
> > compilers, I'm not sure if we could improve generated code or
> > not... but we certainly could improve source code readibility if we
> > were allowed to write 3-way branches like this.
>
> > What would it look like? Obviously the Fortran syntax wouldn't be
> > helpful as-is, because C++ code doesn't have line numbers.
>
> Fortran doesn't have line numbers. It has labels, just like C/C++.
> With the difference that the syntax for a label was [1-9][0-9]*.

I knew that what I called "line numbers" did not, in fact, number
every line... I guess I used the wrong name for them, but I was in
fact referring to labels.

> > 1. We could use labels:
> > if (strcmp(a,b)) less_than, equal_to, greater_than;
> > // Does a "goto" to one of these labels
> > This might present parser problems, if it isn't immediately obvious
> > that less_than, equal_to, and greater_than are all "goto" targets.
>
> It's not obvious at all. What you have written is already legal C/C++,
> with well defined semantics.

Unless, of course, less_than, equal_to, and greater_than aren't
rvalues.

Maybe this would work better?
goto (strcmp(a,b)) less_than, equal_to, greater_than;

> > 2. Or maybe just the presence of certain symbols after the if
> > condition:
> > if (strcmp(a,b)) < { /* ... less-than ... */ }
> > == { /* ... equal ... */ }
> > > { /* ... greater-than ... */ }
>
> > Although I can imagine problems where people assume they could use,
> > for instance, != or <= (there is no need for this 'cause existing if()
> > could create such conditions).
>
> This is interesting. At present, there is no way a legal program can
> contain a '<' as the first token after the closing ) of the if block.

Nor ==. I'm not sure about >.

The problems that I mentioned would be with comprehension by humans,
not parsing by the compiler.

> > 3. Or we could simply expand switch() to allow ranges:
> > switch (strcmp(a,b)) {
> > case 0: /* ... equal ... */ break;
> > case <0: /* ... less-than ... */ break;
> > case >0: /* ... greater-than ... */ break;
> > }
> > I am aware of a workaround for this that works now:
>
> > inline int threeway(int value) { return (value<0)?-1 : (value>0)?1 :0; }
> > // ...
> > switch (threeway(strcmp(a,b))) {
> > case 0: /* ... equal ... */ break;
> > case -1: /* ... less-than ... */ break;
> > case 1: /* ... greater-than ... */ break;
> > }
>
> > But this is non-obvious and inconvenient.
>
> Non-obvious, because it isn't part of the standard. It seems less
> non-obvious than a function remove that doesn't remove anything, or a
> set that is in fact a balanced tree:-). Or the fact that modulo types
> are spelled "unsigned".

Very good points.

> (Note that Fortran has a standard function with
> exactly the semantics of threeway. It's called sign.)

Ah yes... it's coming back to me now.

Quite elegant; extremely expressive, and very flexible.

Suppose for a moment that we didn't want a new keyword 'select'. I
think we could use almost exactly this syntax, except that we would
still need to use break statements. The existing switch statement
would them become a special case of the new switch statement.

(The new switch would no doubt be called the Kanze switch, at least
informally.)

> Personally, I don't think switch et al. is important enough in C++ to
> bother with correcting it, but if we did, I would envisage something
> like the above.

Virtual functions and such reduce the need for switch statements, but
they are still a vitally important part of the language, IMHO.

> Failing that (and I really don't think it worth the
> bother), I wouldn't oppose a standard template function sign, with the
> semantics:
>
> template< typename T >
> int
> sign( T op1 , T op2 )
> {
> return op1 < op2 ? -1 : op2 < op1 : 1 ? 0 ;
> }

(In namespace std, I'm sure you meant.)

Standardizing this might improve the likelihood of some compilers
optimizing it's use in switch() statements with the obvious three
cases.

Even if it doesn't get any special optimization, I still see it
being quite useful:
float my_abs(float x) { return x * std::sign(x); }

or:
// Usage: calc(a,b,'P') returns a+b
// calc(a,b,'M') returns a-b
// Assumptions: 'M' < 'N' < 'P'
int calc(int a, int b, char op) {
return a + std::sign(op-'N')*b;

James Kanze

unread,
May 4, 2003, 5:16:00 PM5/4/03
to
all...@my-dejanews.com (Allan W) writes:

[...]

|> > > 1. We could use labels:
|> > > if (strcmp(a,b)) less_than, equal_to, greater_than;
|> > > // Does a "goto" to one of these labels
|> > > This might present parser problems, if it isn't immediately
|> > > obvious that less_than, equal_to, and greater_than are all
|> > > "goto" targets.

|> > It's not obvious at all. What you have written is already legal C/C++,
|> > with well defined semantics.

|> Unless, of course, less_than, equal_to, and greater_than aren't
|> rvalues.

True. I guess it is rather uncommon for people to use the same names
for labels and for variables. Although to tell the truth, I wouldn't
really know. I don't think I've ever used a label in C or C++ code.

|> Maybe this would work better?
|> goto (strcmp(a,b)) less_than, equal_to, greater_than;

It's an idea. Since goto cannot be presently followed by a (, it
can't break any legal code.

But it doesn't solve the real problem: spaghetti.

|> > > 2. Or maybe just the presence of certain symbols after the if
|> > > condition:
|> > > if (strcmp(a,b)) < { /* ... less-than ... */ }
|> > > == { /* ... equal ... */ }
|> > > > { /* ... greater-than ... */ }

|> > > Although I can imagine problems where people assume they could
|> > > use, for instance, != or <= (there is no need for this 'cause
|> > > existing if() could create such conditions).

|> > This is interesting. At present, there is no way a legal
|> > program can contain a '<' as the first token after the closing )
|> > of the if block.

|> Nor ==. I'm not sure about >.

I suspect that > is less likely than <. But we'd better verify all of
the oddities in templates.

|> Very good points.

|> > or

|> > Classical switch:

|> > and many other variants.

The goal was to have exactly one way of expressing each of the major
structures (selection, looping, assignment and procedure call). Given
that goal, the solution is obvious: add enough options to the syntax
to express whatever is needed:-).

|> Suppose for a moment that we didn't want a new keyword 'select'. I
|> think we could use almost exactly this syntax, except that we
|> would still need to use break statements. The existing switch
|> statement would them become a special case of the new switch
|> statement.

And otherwise would be default:-). Quite frankly, while I think it's
doable, I'm very dubious as to whether it is worth the effort. (If I
were to invest any effort in something along these lines, it would be
making switch work correctly, without the need of break. But I find
that the current situation can be lived with, and that there are even
more important issues to be solved.)

|> (The new switch would no doubt be called the Kanze switch, at
|> least informally.)

|> > Personally, I don't think switch et al. is important enough in
|> > C++ to bother with correcting it, but if we did, I would
|> > envisage something like the above.

|> Virtual functions and such reduce the need for switch statements,
|> but they are still a vitally important part of the language, IMHO.

They == switch statements, I presume. (My understanding of English
grammar is that in such cases, the antecedant of "they" would be the
subject of the clause preceding the but.)

I agree. It's not like goto; I still use them in specific cases. But
while the current syntax has some major flaws, it's not as if we
cannot live with it.

|> > Failing that (and I really don't think it worth the bother), I
|> > wouldn't oppose a standard template function sign, with the
|> > semantics:

|> > template< typename T >
|> > int
|> > sign( T op1 , T op2 )
|> > {
|> > return op1 < op2 ? -1 : op2 < op1 : 1 ? 0 ;
|> > }

|> (In namespace std, I'm sure you meant.)

I'm not sure. If it is to be viewed as an essential part of switch,
then perhaps it should be handled like operator new (which is in the
global namespace). No strong opinions, frankly.

|> Standardizing this might improve the likelihood of some compilers
|> optimizing it's use in switch() statements with the obvious three
|> cases.

Perhaps. The C standard went out of its way to make verifying
implementations legal. But I haven't seen any. But you're probable
right: if it is standardized, people will use it, and if people use
it, compilers will think of how to optimize it.

|> Even if it doesn't get any special optimization, I still see it
|> being quite useful:

|> float my_abs(float x) { return x * std::sign(x); }

Which would probably be slower (and less readable) than the classic
implementation.

|> or:
|> // Usage: calc(a,b,'P') returns a+b
|> // calc(a,b,'M') returns a-b
|> // Assumptions: 'M' < 'N' < 'P'
|> int calc(int a, int b, char op) {
|> return a + std::sign(op-'N')*b;
|> }

Again, I find a more obvious implementation more readable. The real
use remains a three way switch.

Anyway, I do think that there is enough reasonable use to propose it
as an addition to the library. Other than that, while the rest of the
above has an intellectual interest to me, I don't find any of it worth
the effort necessary for standardization, and I certainly don't have
the time myself to follow through with it.

--
James Kanze mailto:ka...@gabi-soft.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

---

James Kanze

unread,
May 4, 2003, 5:44:17 PM5/4/03
to
Si...@sfbone.fsnet.co.uk ("Simon F Bone") writes:

[...]


|> > What has been pretty well established, I think, is that it is
|> > easier to get more accurate results, and above all, to know just
|> > how accurate your results are, with powers of two.

|> Well, I think (in essence ;-)) that how accurate you *know* your
|> results are is what deterimines their accuracy...

Quite my opinion, at any rate. (On the other hand, there seem to be
people who consider that if it doesn't crash...)

|> Anyway, there is little point in my trying to pretend to be an
|> expert on this. The paper I referred to says it all far better
|> than I could.

Sounds like something we have in common. My knowledge of floating
point arithmetic is just sufficient for me to know that I shouldn't be
using it myself.

--
James Kanze mailto:ka...@gabi-soft.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

11 rue de Rambouillet, 78460 Chevreuse, France Tel. +33 1 41 89 80 93

---

Allan W

unread,
May 7, 2003, 5:33:38 AM5/7/03
to
> allan w...@my-dejanews.com (Allan W) writes:
> |> Maybe this would work better?
> |> goto (strcmp(a,b)) less than, equal to, greater than;

ka...@alex.gabi-soft.fr (James Kanze) wrote


> It's an idea. Since goto cannot be presently followed by a (, it
> can't break any legal code.
>
> But it doesn't solve the real problem: spaghetti.

I'll agree that the new 3-way switch or goto would be of use in the
next obfuscated C contest (presuming they allow C++). But that doesn't
mean it isn't useful. You could just as easily argue that the current
if or if/else isn't needed, because we can do the same thing with switch
and (almost always) the trinary operator. (You could also do the same
thing with for and while, but that's just showing off.)

I think that the essence of our distinct viewpoints boils down to this:

> The goal was to have exactly one way of expressing each of the major
> structures (selection, looping, assignment and procedure call). Given
> that goal, the solution is obvious: add enough options to the syntax
> to express whatever is needed:-).

Right or wrong, clearly this was NOT the intent of the whole C++
committee, of Bjarne Stroustrup, of the C committee, of Kernigan and
Ritchie, etc.

The goal is interesting. With fewer ways to express the same algorithm,
programmers might make fewer errors, which might be easier to catch in
code reviews, the compiler would be easier to write and might do a
better job of optimizing, analysis and documentation tools would be
easier to create, etc., etc.

On the other hand, I've had experience with one language (*) that works
this way. It was one of the worst years of my life; ten years later, I
still haven't quite recovered.

(*) The language was CSP (Cross Systems Program), IBM's attempt at a 4GL.
To be fair, this is my only real experience with a 4GL; perhaps others
don't suck so much.

> |> Virtual functions and such reduce the need for switch statements,
> |> but they are still a vitally important part of the language, IMHO.
>
> They == switch statements, I presume. (My understanding of English
> grammar is that in such cases, the antecedant of "they" would be the
> subject of the clause preceding the but.)

Hmm, perhaps not my most poetic work. I meant to say: Virtual functions
reduce the need for switch statements, but they don't make switch
statements totally obsolete. Switch statements are a vital part of the
language. In any given program, it would be possible to replace
switch statements with chained if/else statements -- but it would be
harder to write, read, and maintain. Switch statements help the C++
language to remain expressive.

> I agree. [The switch statement is] not like goto; I still use


> them in specific cases. But while the current syntax has some
> major flaws, it's not as if we cannot live with it.

I wish there was a way to create break-less switches without breaking
existing code. I doubt that there is, unless we introduce a new keyword.

> |> > Failing that (and I really don't think it worth the bother), I
> |> > wouldn't oppose a standard template function sign, with the
> |> > semantics:
>
> |> > template< typename T >
> |> > int
> |> > sign( T op1 , T op2 )
> |> > {
> |> > return op1 < op2 ? -1 : op2 < op1 : 1 ? 0 ;
> |> > }
>
> |> (In namespace std, I'm sure you meant.)
>
> I'm not sure. If it is to be viewed as an essential part of switch,
> then perhaps it should be handled like operator new (which is in the
> global namespace). No strong opinions, frankly.

You yourself added the phrase "standard template function sign." I
don't see any reason why it wouldn't go into namespace std. Furthermore,
this approach is less likely to break existing code.

> |> Standardizing this might improve the likelihood of some compilers
> |> optimizing it's use in switch() statements with the obvious three
> |> cases.
>
> Perhaps. The C standard went out of its way to make verifying
> implementations legal. But I haven't seen any. But you're probable
> right: if it is standardized, people will use it, and if people use
> it, compilers will think of how to optimize it.

Yes, that's what I meant.

> |> Even if it doesn't get any special optimization, I still see it
> |> being quite useful:
>

> |> float my abs(float x) { return x * std::sign(x); }


>
> Which would probably be slower (and less readable) than the classic
> implementation.

It's probably either slower or the same speed, yes. And I agree that
some (many?) programmers would find it harder to read, but some
mathemeticians might even find it easier to read.

> Anyway, I do think that there is enough reasonable use to propose it
> as an addition to the library.

Thank you.

> Other than that, while the rest of the
> above has an intellectual interest to me, I don't find any of it worth
> the effort necessary for standardization, and I certainly don't have
> the time myself to follow through with it.

I understand.

James Kanze

unread,
May 7, 2003, 1:11:20 PM5/7/03
to
all...@my-dejanews.com (Allan W) wrote in message
news:<7f2735a5.03050...@posting.google.com>...

> > allan w...@my-dejanews.com (Allan W) writes:
> > |> Maybe this would work better?
> > |> goto (strcmp(a,b)) less than, equal to, greater than;

> ka...@alex.gabi-soft.fr (James Kanze) wrote
> > It's an idea. Since goto cannot be presently followed by a (, it
> > can't break any legal code.

> > But it doesn't solve the real problem: spaghetti.

> I'll agree that the new 3-way switch or goto would be of use in the
> next obfuscated C contest (presuming they allow C++). But that doesn't
> mean it isn't useful. You could just as easily argue that the current
> if or if/else isn't needed, because we can do the same thing with
> switch and (almost always) the trinary operator. (You could also do
> the same thing with for and while, but that's just showing off.)

I'm not saying that it has no use. Just that it doesn't seem useful
enough to justify the effort of adding it to the language.

> I think that the essence of our distinct viewpoints boils down to
> this:

> > The goal was to have exactly one way of expressing each of the major
> > structures (selection, looping, assignment and procedure call).
> > Given that goal, the solution is obvious: add enough options to the
> > syntax to express whatever is needed:-).

> Right or wrong, clearly this was NOT the intent of the whole C++
> committee, of Bjarne Stroustrup, of the C committee, of Kernigan and
> Ritchie, etc.

No. It was my goal in designing an experimental language. I wanted to
see what the implications were, not necessarily develope something
useful.

> The goal is interesting. With fewer ways to express the same
> algorithm, programmers might make fewer errors, which might be easier
> to catch in code reviews, the compiler would be easier to write and
> might do a better job of optimizing, analysis and documentation tools
> would be easier to create, etc., etc.

> On the other hand, I've had experience with one language (*) that
> works this way. It was one of the worst years of my life; ten years
> later, I still haven't quite recovered.

Well, I don't know that my language was that great:-).

> (*) The language was CSP (Cross Systems Program), IBM's attempt at a
> 4GL. To be fair, this is my only real experience with a 4GL; perhaps
> others don't suck so much.

> > |> Virtual functions and such reduce the need for switch
> > |> statements, but they are still a vitally important part of the
> > |> language, IMHO.

> > They == switch statements, I presume. (My understanding of English
> > grammar is that in such cases, the antecedant of "they" would be the
> > subject of the clause preceding the but.)

> Hmm, perhaps not my most poetic work. I meant to say: Virtual
> functions reduce the need for switch statements, but they don't make
> switch statements totally obsolete. Switch statements are a vital part
> of the language. In any given program, it would be possible to replace
> switch statements with chained if/else statements -- but it would be
> harder to write, read, and maintain. Switch statements help the C++
> language to remain expressive.

To which I agree. I still use switch from time to time.

> > I agree. [The switch statement is] not like goto; I still use them
> > in specific cases. But while the current syntax has some major
> > flaws, it's not as if we cannot live with it.

> I wish there was a way to create break-less switches without breaking
> existing code. I doubt that there is, unless we introduce a new
> keyword.

I would like what I would call a working switch statement, in which each
case was a block (or a single instruction, which could be a compound
instruction). Like the three way go to, however, I don't think that the
benefits are enough to justify the effort.

> > |> > Failing that (and I really don't think it worth the bother), I
> > |> > wouldn't oppose a standard template function sign, with the
> > |> > semantics:

> > |> > template< typename T >
> > |> > int
> > |> > sign( T op1 , T op2 )
> > |> > {
> > |> > return op1 < op2 ? -1 : op2 < op1 : 1 ? 0 ;
> > |> > }

> > |> (In namespace std, I'm sure you meant.)

> > I'm not sure. If it is to be viewed as an essential part of switch,
> > then perhaps it should be handled like operator new (which is in the
> > global namespace). No strong opinions, frankly.

> You yourself added the phrase "standard template function sign." I
> don't see any reason why it wouldn't go into namespace std.
> Furthermore, this approach is less likely to break existing code.

I wrote "standard template function" because I was considering a
function which would be part of the standard, and which is a template.

As I say, I have no strong opinions about the issue, but I suspect that
logically, you're right, and that it goes in std::.

--
James Kanze GABI Software mailto:ka...@gabi-soft.fr


Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung

11 rue de Rambouillet, 78460 Chevreuse, France, Tél. : +33 (0)1 30 23 45 16

---

Ben Hutchings

unread,
May 7, 2003, 1:54:41 PM5/7/03
to
In article <7f2735a5.03050...@posting.google.com>, Allan W wrote:
> ka...@alex.gabi-soft.fr (James Kanze) wrote
<snip>
>> I agree. [The switch statement is] not like goto; I still use
>> them in specific cases. But while the current syntax has some
>> major flaws, it's not as if we cannot live with it.
>
> I wish there was a way to create break-less switches without breaking
> existing code. I doubt that there is, unless we introduce a new keyword.
<snip>

There's no need for a new keyword when there are so many tokens that could
be (ab)used after switch instead of an open-parenthesis. Let me suggest
the "switch++" statement. :-)

Balog Pal

unread,
May 7, 2003, 5:58:16 PM5/7/03
to

===================================== MODERATOR'S COMMENT:
Please wrap lines at <78 columns.


===================================== END OF MODERATOR'S COMMENT

"James Kanze" <ka...@alex.gabi-soft.fr> wrote in message news:867k9gh...@alex.gabi-soft.fr...

|> Order is indeed a problem. Serious problem that hits. And one that
|> IMO shall be covered ASAP. But It is an unrelated issue.

>It's not. Once you allow dynamic initialization, you have order of
initialization problems.

By 'unrelated' I meant it's a problem that will supposedly be solved on its own route. And that solution will cover this instance of the problem.

|> > The current rules guarantee that the initialization will occur
|> > before the first use after main of anything in the translation
|> > unit that contains the definition. What does that mean here?

|> I see no problem in implementing the order to make the
|> initialisatoion before anythng that follows the object.

>In every compilation unit in which it is included? What do you do in
>the case of conflicts?

There are no conflicts with the 'before' case.

|> But you're right, another thing can contradict the current order
|> rules: that the initialisation happens _after_ anything that is
|> before this object in the translation unit. But I think is more
|> like a theoretucal problem, and can be covered by ODR. (If it's
|> not clear what I mean, please just read on. )

Let's have module A; objects encountered as a11, a12, i1, i2, b11, b12. And module B, with objects a21, a22, i1, i2, b21, b22. i1 and i2 are the 'inline' objects.

The linker will see modules A then B, and generates a list of initialisers a11, a12, i1, i2, b11, b12, a21, a22, b21, b22. For B then A, it will be a21, a22, i1, i2, b21, b22, a11, a12, b11, b12.

Note, that i* is initialised before _any_ bXX whatever you do. Any object that appears _after_ an inline will find it surely initialised by the time of it's own init. i1 is inited either at its own place in order (it it is the first module having it) or it is inited well before the first item in this module (for the other case).

The problematic case can be the init of i itself. Suppose i1 is dependent on a11. Or i2 dependent on i1. But for those cases you must really fight to shoot yourself in the leg. Like using extern i1; int one module and inline i1 in another. If that is considered a dangerous case, it can be promoted from general ODR issue to one diagnosed at compile time. (The compiler can see the contradicting declarations as it can catch extern/static now.)

>The problem isn't generating the code or getting just one version
>linked in. The proble is when to call it.

And what that problem? Call it at the natural place for the first instance, discard the others. Or I could even accept the trick used for scoped statics using a flag.

>The current rules define order within a compilation unit. And there
>must be a single definition, so it is in a specific compilation unit.
>Your extension allows the same initialization to be specified in
>several compilation units. With perhaps a conflicting order.

IMHO for any practical use you get all the init guarantees one may want. Certainly if the ony acceptable aim is 'nothing can be chaged a bit' that is not possible to achieve, but that prevents any progress, does it?

>It probably isn't a killer problem. But it is an issue which has to
>be addressed. Addressing it takes work, even if there were a trivial
>solution. And to date, I've yet to see any benefits which would
>accrue from such work.

I think the solution IS on that trivial level.
And I see the benefit in removing forced redundancy for redular objects. And tons of hassle for templates, that want a static member.
And finally letting go the const->static hack is a benefit in my eyes too.

>First, it would be nice if you'd talk about things everyone could
>understand. I have no idea what you mean by selectany; it certainly
>isn't part of my compiler technology vocabulary. From your
>description, I think it works vaguely something like Fortran named
>common blocks. In which case, there's nothing new about it.

DOH. I thought I'm clear enough with the examples, also everypne can access more info from MSDN. Here's whet MS says on selectany:
- ------------------
selectany
Microsoft Specific ®

__declspec( selectany ) declarator

This attribute tells the compiler that the declared global data item is a pick-any COMDAT (a packaged function). At link time, if multiple definitions of COMDAT are seen, the linker picks one and discards the rest. See linker option /OPT:REF (Optimizations). If the linker option /OPT:REF is selected, then COMDAT elimination will occur to remove all the unreferenced data items in the linker output.

A global data item can normally be initialized only once in an EXE or DLL project. This attribute can be used in initializing global data defined by headers, when the same header appears in more than one source file. This attribute is available in both the C and C++ compilers.

Note This attribute can only be applied to the actual initialization of global data items that are externally visible.

END Microsoft Specific

Example

This code shows how to use the selectany attribute:

//Correct - x1 is initialized and externally visible
__declspec(selectany) int x1=1;

//Incorrect - const is by default static in C++, so
//x2 is not visible externally (This is OK in C, since
//const is not by default static in C)
const __declspec(selectany) int x2 =2;

//Correct - x3 is extern const, so externally visible
extern const __declspec(selectany) int x3=3;

//Correct - x4 is extern const, so it is externally visible
extern const int x4;
const __declspec(selectany) int x4=4;

//Incorrect - __declspec(selectany) is applied to the uninitialized
//declaration of x5
extern __declspec(selectany) int x5;
- ------------------

>What extension? MS allows static const floating point to be
>initialized in the class?

The old versions I actually use doesn't even allow to init an int. :-/
As you see MS' selectany is for namespace scoped stuff.

But what is the difference between a class static and a namespace data object? I see no difference but the scope of the identifier. Having one mechansm implemented why not use it anywhere it can be used?

|> Well, let's see what we have now:

|> // .h file:
|> extern Object o; // extern no possible init here
|> const Object co("foo");
|> // .cpp file:
|> Object o("foo");

|> Using what I propose, we could write:
|> //.h file
|> inline Object o("foo");
|> inline const Object co("foo");

|> The original version works only because C++ used a trick making
|> const default to static. So using that we'll have a private copy
|> of co in every unit. Hopefully everyone RTFM and do not think
|> their address are unique. Sure, the compiler will just opt away
|> the object it it can.

|> The inline one is a regular object with external linkage. The
|> whole program will have exactly one. Just similar way we have
|> template functions and inline functions.

>And when does initialization take place?

As described above. Do you see any problem with the most natural way the linkers arrange the order?

The important issue is that objects coming _after_ the definition shall never encounter a not yet inited object. That is achieved.

|> It is allowed to see the definition multiple times in a single
|> translation unit. (That is not the case for const int x=1; stuff!
|> ) Certainly the same thing can be used in a class:

>Nobody is denying any of this. The question is mainly one of when
>initialization takes place.

Well?

Paul

0 new messages