Re: floating-point literal cannot appear in a constant-expression
On Mar 6, 11:39 am, "Alf P. Steinbach" <al...@start.no> wrote:
* TimC:
g++ 4.x -pedantic doesn't allow me to do this:
static const long int DOME_WANDER =
int(TcsAbsDomeToArcsec*1.25/TcsIncDomeToArcsec);
(minimal code is below)
in a class declaration, and gives:
In file included from TcsEncoderTask.C:232:
AbsIncPositionTracker.h:189: error: floating-point literal cannot appea=
r in a constant-expression
The message is wrong: it should be "floating-point literal
cannot appear in an integral constant-expression unless it is
immediately converted to integral or enumeration type."
First off, is that truly illegal code (TcsAbsDomeToArcsec
and TcsIncDomeToArcsec are just #defines of floats)
according to the standards?
Yes.
And secondly, if this is truly illegal and not just a
mundane bug in gcc, tell me, what would be the point of
illegalising that, and what do I do to get around it?
The motivation was not to require cross-compilers to implement
the floating point arithmetic of the target machine. Without
implementing the exact floating point arithmetic of the target
machine, the value might not be the same as if the expression
was evaluated at runtime.
IMHO, whether this is a valid motivation is arguable, given that
the exact results of the expression at runtime are allowed to
vary.
Surely a cast (it's been a while since I've done C/C++, so I
tried several different casts, none of which worked) is
sufficient to convince both a compiler and a language lawyer
that yes, I know it's a float, but an int is perfectly
acceptable for my purposes? Initialising DOME_WANDER to be
a pure int not calculated from those above floats would be
fragile and a serious pain.
Absolutely minimal code:
cat asd.C
#define TcsAbsDomeToArcsec (10.5469 * 60.0)
#define TcsIncDomeToArcsec 0.150
class AbsIncPositionTracker {
static const long int DOME_WANDER = (long int)(TcsAbsDomeToArcsec*=
1.25/TcsIncDomeToArcsec);
And the initialization within the class requires an integral
constant expression.
};
int main (int, char**)
{
return 0;
}
g++ -c -ansi -Wall -W -pedantic asd.C
asd.C:6: error: floating-point literal cannot appear in a constant-expr=
ession
asd.C:6: error: floating-point literal cannot appear in a constant-expr=
ession
asd.C:6: error: floating-point literal cannot appear in a constant-expr=
ession
asd.C:6: error: floating-point literal cannot appear in a constant-expr=
ession
<comeau>
Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2
Copyright 1988-2008 Comeau Computing. All rights reserved.
MODE:strict errors C++ C++0x_extensions
"ComeauTest.c", line 6: error: expression must have integral or enum type
static const long int DOME_WANDER = (long
int)(TcsAbsDomeToArcsec*1.25/TcsIncDomeToArcsec);
"ComeauTest.c", line 6: error: expression must have integral or enum type
static const long int DOME_WANDER = (long
int)(TcsAbsDomeToArcsec*1.25/TcsIncDomeToArcsec);
"ComeauTest.c", line 6: error: expression must have integral or enum type
static const long int DOME_WANDER = (long
int)(TcsAbsDomeToArcsec*1.25/TcsIncDomeToArcsec);
"ComeauTest.c", line 6: error: expression must have integral or enum type
static const long int DOME_WANDER = (long
int)(TcsAbsDomeToArcsec*1.25/TcsIncDomeToArcsec);
4 errors detected in the compilation of "ComeauTest.c".
</comeau>
Formally this is due to =A75.19/1, which states that "An
/integral constant- expression/ can involve only literals
(2.13), enumerators, const variables or static data members of
integral or enumeration types initialized with constant
expressions (8.5), non-type template parameters of integral or
enumeration types, and sizeof expressions. Floating literals
can appear only if they are cast to integral or enumeration
types." Further on it mentions that you can't use pointers,
references, or comma expressions, not even function calls.
FWIW: this is being extended. I'm pretty sure, for example,
that certain functions (declared constexpr) will be allowed. I
don't know too much about what else, however.
But as far as I know it's only a political thing, same no-good
reason that you can't initialize a floating point class static
in that way.
More historical than political, I think. There are really two
separate issues: the fact that the initialization expression in
this context must be an integral constant expression, and the
fact that floating point arithmetic cannot be used in an
integral constant expression.
Because you can express the same just with a little different
syntax:
A little:-)?
<code>
namespace tcs {
double const absDomeToArcsec = 10.5469 * 60.0;
double const incDomeToArcsec = 0.150;
} // namespace tcs
template< typename Dummy >
struct DomeWander_
{
static long const domeWander;
};
template< typename Dummy >
long const DomeWander_<Dummy>::domeWander =
(long int)(tcs::absDomeToArcsec*1.25/tcs::incDomeToArcsec);
class AbsIncPositionTracker
: private DomeWander_<void> // domeWander
{};
int main ()
{}
</code>
The difference is that when the value isn't specified in the
in-class declaration, it's no longer restricted to /integral
constant-expression/.
That would cover his minimal example. It's worth noting however
that in this case, domeWander is not an integral constant
expression; it can't be used as an array bounds, for example
(and theoretically, at least, you could access it before it was
initialized, and read 0). I don't know if that's a problem in
his actual code, however.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34