 |
C++Talk.NET C++ language newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Matthew Wilson Guest
|
Posted: Tue Aug 26, 2003 8:33 am Post subject: Why not floating-point member constants? |
|
|
I've searched a fair bit on this point, and found plenty of references
to the inconsistency, but not found one explaining it.
Is there a good reason why
class Maths
{
const double pi = 3.141592653590;
};
is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
Thanks in advance
Matthew Wilson
STLSoft moderator and C++ monomaniac
mailto:matthew (AT) stlsoft (DOT) org
http://www.stlsoft.org
news://news.digitalmars.com/c++.stlsoft
"You can tell a Yorkshireman, but you can't tell him much!" -- Uncle
Michael
-------------------------------------------------------------------------------
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Albuschat Guest
|
Posted: Tue Aug 26, 2003 6:36 pm Post subject: Re: Why not floating-point member constants? |
|
|
Matthew Wilson wrote:
| Quote: | I've searched a fair bit on this point, and found plenty of references
to the inconsistency, but not found one explaining it.
Is there a good reason why
class Maths
{
const double pi = 3.141592653590;
};
is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
|
It's just illegal syntax.
C++ doesn't allow initialisation on members that
way. You have to use initialisation lists instead (see second
code snippet).
It should read
class Maths {
static const double pi;
};
const double Maths::pi = 3.1415;
or, alternitavely
class Maths {
const double pi;
Maths(): pi(3.1415) { };
};
but this way you'll have a pi for every instance,
what might not be what you want.
cu, Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Attila Feher Guest
|
Posted: Tue Aug 26, 2003 6:41 pm Post subject: Re: Why not floating-point member constants? |
|
|
Matthew Wilson wrote:
| Quote: | I've searched a fair bit on this point, and found plenty of references
to the inconsistency, but not found one explaining it.
Is there a good reason why
class Maths
{
const double pi = 3.141592653590;
};
is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
|
Verry simple.
The latter is a variable *definition*. It does define the variable, since
it is initialized. So the variable is given memory etc.
The former is a class member declaration. Important to note that it is not
allowed (for obvious reasons) to define a member variable inside a class
declaration, not even a static one. Why. Because the class declaration is
only a description of what the class (its structure) will be, it does not
actually create anything runtime (including but not limited to constant
variables).
There is a notable exception for the above rule and that is (except in
MSVC6) the definition (and declaration) of integral constants inside a class
declaration is allowed. Why are they allowed? Because they allocate no
memory.
For your above headache I would make a pretty simple trick:
// Something like this,
// all inline
class PI {
const double pie;
public:
PI():pie(3.141592653590) { ; }
operator double() const
{ return pie; }
};
// Pie is a bad joke,
// syntax might be terrible
// and then
struct Maths {
PI pi;
};
This saves you the initialization of pi in each constructor for Math.
| Quote: | "You can tell a Yorkshireman, but you can't tell him much!" -- Uncle
Michael
|
Is that an insult to Yorkshireman or a complement? ;-)
--
Attila aka WW
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Spangenberg Guest
|
Posted: Tue Aug 26, 2003 6:43 pm Post subject: Re: Why not floating-point member constants? |
|
|
Hello Matthew Wilson,
Matthew Wilson schrieb:
| Quote: | I've searched a fair bit on this point, and found plenty of references
to the inconsistency, but not found one explaining it.
Is there a good reason why
class Maths
{
const double pi = 3.141592653590;
};
is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
|
I think we have to consider two problem phases:
1) Classes may contain static and non-static members. This
concept does not fit into namespaces, so we have to decide,
which of these data member concepts of classes are
compared with data concepts of namespaces. The current
standard does not explicitely mention data members of
namespaces (as far as I know), but I think we can legitimately
assume, that the same rules apply as those of any members
in namespace scopes (3.3.5). Data objects in namespace scope
with linkage (either internal or external) do have static storage
duration.
2) While constant non-static data members **need** their
initialization in any called c'tor they must be initialized there
(in the initialization list). Static data members are not part
of each individual object (instance) of the corresponding class,
but exists only once in the program (if at all) and do have static
storage duration and external linkage.
The legitimate question now is whether
class Maths
{
static const double pi = 3.141592653590;
};
should be valid or not. I think we have to exclude non-static
data members from this discussion, because
1) They are usually initilized with values which are determined
at run-time and which are **not** ICE.
2) If they were initialized via ICE, they could be immediately
"promoted" to a static member, since an ICE is never an
object individual property.
Currently the above mentioned syntax is limited for types
which are either integral or of enumeration type and where
the initialization expression is an ICE. I know that some
compilers also extend this initialization for e.g. floating-point
types (was it gcc?) and thus must extend the validity of
initialization expressions.
I don't see any real problem to extend the Standard to allow
such in-class-initializations of static members, but lets see, what
others have to say...
Greetings from Bremen,
Daniel Spangenberg
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Tue Aug 26, 2003 6:46 pm Post subject: Re: Why not floating-point member constants? |
|
|
In article <5d33192c.0308251953.76d5d580 (AT) posting (DOT) google.com>, Matthew
Wilson <stlsoft (AT) hotmail (DOT) com> writes
| Quote: | I've searched a fair bit on this point, and found plenty of references
to the inconsistency, but not found one explaining it.
Is there a good reason why
class Maths
{
const double pi = 3.141592653590;
};
|
Within the grammar of the language a class definition consists of
declarations. The above statement would be a definition. There is a
special exemption allowed for initialising static const integer members
in class, but strictly speaking even those have to have a unique point
(i.e. generally not in a header file which may be included into several
TUs) of definition provided out of class.
| Quote: |
is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
|
Because that is a definition. However note that you still need to be
careful that you do not get redefinition errors at link time.
--
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Ryan Winter Guest
|
Posted: Tue Aug 26, 2003 7:04 pm Post subject: Re: Why not floating-point member constants? |
|
|
There is a very good reason.
Initialisation cannot be done within a class.
Ryan
Matthew Wilson wrote:
| Quote: | I've searched a fair bit on this point, and found plenty of references
to the inconsistency, but not found one explaining it.
Is there a good reason why
class Maths
{
const double pi = 3.141592653590;
};
is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
|
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Matthew Wilson Guest
|
Posted: Wed Aug 27, 2003 9:29 am Post subject: Re: Why not floating-point member constants? |
|
|
[email]stlsoft (AT) hotmail (DOT) com[/email] (Matthew Wilson) wrote in message news:<5d33192c.0308251953.76d5d580 (AT) posting (DOT) google.com>...
| Quote: | I've searched a fair bit on this point, and found plenty of references
to the inconsistency, but not found one explaining it.
Is there a good reason why
class Maths
{
const double pi = 3.141592653590;
};
is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
|
Gah! Once again I type fast and think slow.
I meant
class Maths
{
static const double pi = 3.141592653590;
};
Matthew
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Spangenberg Guest
|
Posted: Wed Aug 27, 2003 9:51 am Post subject: Re: Why not floating-point member constants? |
|
|
Good Morning, llewelly
llewelly schrieb:
[snip]
| Quote: | Now if you made a typo and intended the first example to read:
class Maths
{
static double const pi = 3.141592653590;
};
The issue is quite different; I think the reason is then
tradition. Traditionally, many class definitions are placed in
header files. Header files are included in multiple seperate
TUs. Anything in a header file (and by extension, in a class
definition ) must then be ODR-immune. 'static double const'
requires storage.
|
One counter example: The same problem arises for any currently allowed
static data member. First, the current standard does not explain strongly
enough, that an instance of such a constant is only necessary in case you
need an object (if you take the address of it or a reference, const of
course).
As far as I remember, this problem is now cleared in TC1.
But independent from this: You must expect, that you need to **define**
even an integral or enumaration static data member in cases where its
address is needed, so a similar problem currently exists.
I would like to propose, that we should extend the in-class-value assignment
of static data members for at least any arithmetic type and in the same
sentence
would extend to allow here arithmetic constant expressions as initializing
values
(instead of only ICE's).
Yours,
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Wed Aug 27, 2003 3:12 pm Post subject: Re: Why not floating-point member constants? |
|
|
In article <biffu0$bpa$1 (AT) newstree (DOT) wise.edt.ericsson.se>, Attila Feher
<attila.feher (AT) lmf (DOT) ericsson.se> writes
| Quote: | There is a notable exception for the above rule and that is (except in
MSVC6) the definition (and declaration) of integral constants inside a class
declaration is allowed. Why are they allowed? Because they allocate no
memory.
|
No, it is still a declaration with an in class initialiser provided.
According to the strict rules a single point of definition is still
required.
--
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
kanze@gabi-soft.fr Guest
|
Posted: Wed Aug 27, 2003 10:12 pm Post subject: Re: Why not floating-point member constants? |
|
|
Francis Glassborow <francis (AT) robinton (DOT) demon.co.uk> wrote
[...]
| Quote: | is not valid, when
namespace Maths
{
const double pi = 3.141592653590;
}
is?
Because that is a definition. However note that you still need to be
careful that you do not get redefinition errors at link time.
|
Not as long as it is const; an object or reference that is explicitly
declared const has internal linkage by default.
--
James Kanze GABI Software mailto:kanze (AT) gabi-soft (DOT) fr
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Matthew Wilson Guest
|
Posted: Thu Aug 28, 2003 2:36 pm Post subject: Re: Why not floating-point member constants? |
|
|
Thomas Richter <thor (AT) cleopatra (DOT) math.tu-berlin.de> wrote
| Quote: | Hi Daniel,
/* snip about
class A {
static const double pi = 3.1415;
};
*/
I don't see any real problem to extend the Standard to allow
such in-class-initializations of static members, but lets see, what
others have to say...
The typical argument against this is that the very same header file
might be seen by different compilers used to compile different modules
of the same project. The problem is now that floating point values cannot
be represented exactly, thus different compilers might assign different
internal representations of "the same" number when generating code making
use of the same header file.
|
Thanks Thomas.
That's an answer I was kind of expecting. My follow-up question is,
then, that isn't code such as the following equally vulnerable to
inconsistencies between compilers:
class Maths
{
public:
static const double pi()
{
return 3.141592653590;
}
};
or this:
namespace Maths
{
return 3.141592653590;
}
Since both these are effortless (in terms of writing and, perhaps, in
terms of thinking through the representational-inconsistencies), it
seems a churlish, not to say misleading, contradiction to bar the use
of member constants.
Furthermore, don't numeric_limits<float / double / long
double>::min()/max() have the same issues?
So, I guess I'm interested to know whether the decision to bar
floating-point member constants was mindful (in which case I'm keen to
learn the rationale) or just an oversight.
Thanks so much for everyone's input so far.
Matthew Wilson
STLSoft moderator and C++ monomaniac
mailto:matthew (AT) stlsoft (DOT) org
http://www.stlsoft.org
news://news.digitalmars.com/c++.stlsoft
"But if less is more, think how much more more will be!" -- Dr Frazier
Crane
-------------------------------------------------------------------------------
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Spangenberg Guest
|
Posted: Thu Aug 28, 2003 8:01 pm Post subject: Re: Why not floating-point member constants? |
|
|
Hello Thomas,
Thomas Richter schrieb:
| Quote: | Hi Daniel,
/* snip about
class A {
static const double pi = 3.1415;
};
*/
I don't see any real problem to extend the Standard to allow
such in-class-initializations of static members, but lets see, what
others have to say...
The typical argument against this is that the very same header file
might be seen by different compilers used to compile different modules
of the same project. The problem is now that floating point values cannot
be represented exactly, thus different compilers might assign different
internal representations of "the same" number when generating code making
use of the same header file.
|
I also have heart of this argumentation and it is true, of course, but:
We are also **allowed** to define floating point constants (and those of
other types)
in namespace scope, either of internal or external linkage:
namespace Maths{
const double pi_in = 3.1415; // internal linkage if not forward declared as
external
extern const pi_ex = 3.1415; // external linkage
}
Since this kind of declaration does not **directly** lead to e.g. different
instantiations
of templates (consider an ACE instead of an ICE as argument of a non-type
template
parameter, which is not allowed), we should not expect unexpected results of
meta
programming techniques.
I don't see, why we should not allow the same in-class-initialized static
constants of
floating point types, because we could deny there partition in ICE's in the
same way
as we have to deny problematic situations like the following:
namespace Maths{
const double three = 3.0 * 1.00001;
const bool is_odd = static_cast<int>(three) % 2;
}
template <bool IsOdd = true>
struct Dimension{
static const int dim = 3;
};
template <>
struct Dimension<false> {
static const int dim = 5;
};
int array[Dimension<Maths::is_odd>::dim];
Since Maths::is_odd is not an ICE, the final
array declaration should result in an error (See
5.19 Constant expressions).
Yours,
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Daniel Spangenberg Guest
|
Posted: Thu Aug 28, 2003 8:02 pm Post subject: Re: Why not floating-point member constants? |
|
|
Daniel Spangenberg schrieb:
| Quote: | 2) While constant non-static data members **need** their
initialization in any called c'tor they must be initialized there
(in the initialization list). Static data members are not part
of each individual object (instance) of the corresponding class,
but exists only once in the program (if at all) and do have static
storage duration and external linkage.
|
I have to constrain my statement to:
"... and do have static storage duration. They have external linkage
**if the name of the class has external linkage**."
Daniel
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Thomas Richter Guest
|
Posted: Thu Aug 28, 2003 8:34 pm Post subject: Re: Why not floating-point member constants? |
|
|
Hi,
| Quote: | No, it is still a declaration with an in class initialiser provided.
According to the strict rules a single point of definition is still
required.
Hm. Sounds interesting. We do not allocate memory for those, claim them to
be good substitutes for macros; we also say that a declaration with an
initializer is always also a definition... and I still need to provide and
out of class definition? That does not make sense.
|
It does not for numbers that have a unique representation, i.e. "integral
constants" (integers). However, the same file can be seen from various
translation units, and hence various compilers. Floats have finite precision,
and thus compilers could assign them slightly different values, dependent
on their internal accuracy when converting these numbers into an internal
representation. That could have the strange and wonderful effect that when
initializing a float variable in one translation unit with the value, and
comparing this with the value you get from another translation unit, you
could very well end up with different values. If you assign memory to
the variable, it is the matter of the linker to make assignments from
this number references to the location where the number was stored at
compile time.
Well, just my two cents...
Greetings,
Thomas
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
Francis Glassborow Guest
|
Posted: Thu Aug 28, 2003 8:36 pm Post subject: Re: Why not floating-point member constants? |
|
|
In article <biis0i$ekf$1 (AT) phys-news1 (DOT) kolumbus.fi>, White Wolf
<wolof (AT) freemail (DOT) hu> writes
| Quote: | Francis Glassborow wrote:
In article <biffu0$bpa$1 (AT) newstree (DOT) wise.edt.ericsson.se>, Attila Feher
[email]attila.feher (AT) lmf (DOT) ericsson.se[/email]> writes
There is a notable exception for the above rule and that is (except
in MSVC6) the definition (and declaration) of integral constants
inside a class declaration is allowed. Why are they allowed?
Because they allocate no memory.
No, it is still a declaration with an in class initialiser provided.
According to the strict rules a single point of definition is still
required.
Hm. Sounds interesting. We do not allocate memory for those, claim them to
be good substitutes for macros; we also say that a declaration with an
initializer is always also a definition...
When? Where? In C declarations of variables are definitions by default |
and we have to use 'extern' to remove the definitional aspect. In C++
the statements that compose a class definition are declarations. We
allow nested classes and member functions to be defined in class because
the language provides sufficient protection to prevent those from
becoming problems even in header files.
It has always been problematical to define a static (i.e. non-local)
variable in a header file. Class members normally have external linkage
and so need a unique point of definition.
| Quote: | and I still need to provide and
out of class definition? That does not make sense.
|
The alternative would have been to do exactly what is done with const
variables in a namespace, provide one copy per TU. And, no, we were not
willing to further mess with the language by requiring a (pre-)linker to
clear up multiple definitions. The special allowance for in class
initialisers for static const integer types was made to allow compile
time use of those values (which is common practice for such things as
dimensions of arrays)
We already have enough problems with order of intialisation across TUs
without making it worse by supporting in class definitions of variables.
--
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
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|