Topic: Whose idea to make it a function?
Author: "kanze" <kanze@gabi-soft.fr>
Date: Mon, 17 Jul 2006 09:41:52 CST Raw View
Gabriel Dos Reis wrote:
> On Wed, 5 Jul 2006, kanze wrote:
> | Unless, of course, the real reason is to allow instantiation for
> | user defined types, for which constant expressions may not be
> | possible. Looking at it, the values with type T are functions,
> | and the others not, so this is possibly a more likely
> | explination.
> Instantiations of the primary template numeric_limits on
> user-defined types are hadly useful without partial or
> explicit specializations.
Agreed. I would expect full explicit specialization. But
typically, a user defined type will not have static
initialization (so if max were a static T object, rather than a
function, you could have order of initialization problems). For
that matter, I imagine that there could be user defined types
where the maximum value cannot be constructed directly at all;
where some sort of expression was needed.
> I suspect that functions offer more general and better abstractions
> layer than plain constants. What was missing was the ability to use
> some simple function return values as constant expressions. That is
> soon corrected. Looking for whose fault or idea it was would hardly
> improve the situation.
I don't think that anyone is trying to pin the blame. Just
curiousity as to how something historically came about.
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Mon, 17 Jul 2006 02:31:51 GMT Raw View
On Tue, 4 Jul 2006, kanze wrote:
| > And given that (in general) methods should be favored over
| > direct access to data (to promote encapsulation), there is a
| > good argument for numeric_limit::max's current implementation.
|
| The problem is that the same interface is imposed on
| std::numeric_limit<char>::max. And there are a lot of things
| you could do with that if it weren't a function.
all this debate is soon pointless given the proposal to make simple
functions like numeric_limit<char>::max() constant expressions.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Mon, 17 Jul 2006 02:32:13 GMT Raw View
On Wed, 5 Jul 2006, kanze wrote:
| Unless, of course, the real reason is to allow instantiation for
| user defined types, for which constant expressions may not be
| possible. Looking at it, the values with type T are functions,
| and the others not, so this is possibly a more likely
| explination.
Instantiations of the primary template numeric_limits on user-defined
types are hadly useful without partial or explicit specializations.
I suspect that functions offer more general and better abstractions
layer than plain constants. What was missing was the ability to use
some simple function return values as constant expressions. That is
soon corrected. Looking for whose fault or idea it was would hardly
improve the situation.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: gdr@cs.tamu.edu (Gabriel Dos Reis)
Date: Mon, 17 Jul 2006 05:57:47 GMT Raw View
On Wed, 5 Jul 2006, Greg Herlihy wrote:
|
| kanze wrote:
| > Greg Herlihy wrote:
| .
| > The problem is that the same interface is imposed on
| > std::numeric_limit<char>::max. And there are a lot of things
| > you could do with that if it weren't a function.
| >
| > The reason std::numeric_limit<>::max is a function is simple:
| > there are implementations where it is impossible to determine
| > the value until runtime---implementations where runtime options
| > may affect it.
|
| The fact that numeric limits are also available as macros in <cfloat>
| rules out the possibility of numeric_limits::max() performing any kind
| of runtime check. There is only ony limit per program per type. So how
| could DBL_MAX and std::numeric_limits<double>::max() ever disagree
| without at least one of them being incorrect?
Fully agreed.
I think the ability for people to specialize numeric_limits<T>::max
for user-defined types should not be underestimated. Making it a data
member would mean that people would have to deal with the nightmarre
of global object initializations. Using functions prevents that can
of worms.
Again, the real issue is the ability to use simple functions in constant
expressions.
--
Gabriel Dos Reis
gdr@cs.tamu.edu
Texas A&M University -- Department of Computer Science
301, Bright Building -- College Station, TX 77843-3112
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Tue, 4 Jul 2006 02:29:46 CST Raw View
Frederick Gotham wrote:
> "Bo Persson" posted:
>
>
> > Because floating point values are not compile time constants. (Think
> > cross-compiler).
>
>
> Hmm... the following snippet suggests otherwise:
>
>
> int main()
> {
> char *p = 25235.25225 ? 0 : 1;
> }
The above program shows that a floating point literal is a compile-time
constant - but that fact was not being questioned. The challenge was to
replace a floating point literal with a symbolic constant - and without
the program being at all affected by the change.
So revising the above program to:
const double kConstDouble = 25235.25225;
int main()
{
char *p = kConstDouble ? 0 : 1; // error: invalid conversion
}
is a better test. And even though this program's logic appears to be
unchanged from the original, it is no longer the same program. This
revised version no compiles successfully because 1 is not a type of
pointer (whereas the original program simply eliminated the false case
of the conditional expression altogether.)
In essence there is really no difference in efficiency whether
numeric_limits<double> is declared as a constant and as an inline
function - because neither is a constant expression. And given that (in
general) methods should be favored over direct access to data (to
promote encapsulation), there is a good argument for
numeric_limit::max's current implementation.
There is also a good argument for changing the rules governing constant
expressions in C++. At least that was my conclusion after reading the
"Generalized Constant Expressions" proposal found here:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1972.pdf
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "kanze" <kanze@gabi-soft.fr>
Date: Tue, 4 Jul 2006 09:47:56 CST Raw View
Greg Herlihy wrote:
> Frederick Gotham wrote:
> > "Bo Persson" posted:
> > > Because floating point values are not compile time
> > > constants. (Think cross-compiler).
This is, in fact, false. A floating point value can be a
constant, although you can't do as much with it as you can with
an integral constant. A floating point constant can even appear
in an integral constant expression, if (and only if) it is
immediately converted to an integral type.
> > Hmm... the following snippet suggests otherwise:
> > int main()
> > {
> > char *p = 25235.25225 ? 0 : 1;
Correct. This is legal because the floating point constant is
immediately converted to bool, which is an itegral type.
> > }
> The above program shows that a floating point literal is a
> compile-time constant - but that fact was not being
> questioned. The challenge was to replace a floating point
> literal with a symbolic constant - and without the program
> being at all affected by the change.
> So revising the above program to:
> const double kConstDouble = 25235.25225;
> int main()
> {
> char *p = kConstDouble ? 0 : 1; // error: invalid conversion
> }
> is a better test.
Except that it's not really relevant. The rules for floating
point constants are different than those for integral constants;
in particular, a floating point value can appear in an integral
expression only if 1) it is a literal and 2) it is converted to
an integral type. In the original example, both conditions
held; here, one has been violated.
> And even though this program's logic appears to be unchanged
> from the original, it is no longer the same program. This
> revised version no compiles successfully because 1 is not a
> type of pointer (whereas the original program simply
> eliminated the false case of the conditional expression
> altogether.)
> In essence there is really no difference in efficiency whether
> numeric_limits<double> is declared as a constant and as an
> inline function - because neither is a constant expression.
Neither is an integral constant expression. The first is still
a constant expression.
> And given that (in general) methods should be favored over
> direct access to data (to promote encapsulation), there is a
> good argument for numeric_limit::max's current implementation.
The problem is that the same interface is imposed on
std::numeric_limit<char>::max. And there are a lot of things
you could do with that if it weren't a function.
The reason std::numeric_limit<>::max is a function is simple:
there are implementations where it is impossible to determine
the value until runtime---implementations where runtime options
may affect it.
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: alfps@start.no ("Alf P. Steinbach")
Date: Tue, 4 Jul 2006 17:21:23 GMT Raw View
* kanze:
>
> The reason std::numeric_limit<>::max is a function is simple:
> there are implementations where it is impossible to determine
> the value until runtime---implementations where runtime options
> may affect it.
I was about to reply that that's close to the ultimate in irrelevant
reasons, but then it occurred to me that it's a very good reason --
for non-integral types. Thanks, it explains not just max() but
potentially much more which has appeared totally mysterious to me so far
(I'll have to think about this when the sun's down & beer consumption
likewise). Oh, let's have back the good old days of emulation and a
zillion different floating point types, it was much more /interesting/!
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "kanze" <kanze@gabi-soft.fr>
Date: Wed, 5 Jul 2006 11:13:04 CST Raw View
"Alf P. Steinbach" wrote:
> * kanze:
[...]
> Oh, let's have back the good old days of emulation and a
> zillion different floating point types, it was much more /interesting/!
FWIW: at least one platform I'm aware of does have two distinct
floating point implementations for double. Modern avatars of
the IBM 390 support both IEEE floating point and the classical
IBM floating point. I'm not too familiar with the details of
how you select; I think it is a flag in a program status word
somewhere. If you can change the selection during program
execution, however, it should lead to some interesting
questions:
setFloatingPointMode( IBM_special::classic ) ;
double d1 = std::numeric_limits<double>::max() ;
setFloatingPointMode( IBM_special::IEEE ) ;
double d2 = std::numeric_limits<double>::max() ;
assert( d1 == d2 ) ; // Will fail !!!
or
setFloatingPointMode( IBM_special::IEEE ) ;
double d1 = std::numeric_limits<double>::max() ;
setFloatingPointMode( IBM_special::classic ) ;
// What is the value of d1 now? The max value of an IEEE
// double is not representable in a classic IBM double.
I rather suspect that in such an implementation, the effect of
calling the implementation defined function setFloatingPointMode
would be to invalidate all existing floating point values in the
program, so that both of these examples would display undefined
behavior. (I can't see any other way to define it. Changing
the floating point mode will not change the bit patterns in
variables in memory.)
Of course, there's still something I don't understand here. By
my reasoning, the same logic which leads to declaring max a
function also applies to digits and digits10 (and in the case
above, to radix). None of which are functions.
Note that the C standard handles this a bit differently. All of
the values in <limits.h>, and all of the integral values in
<float.h> (with one exception), must be constant expressions
suitable for use in #if preprocessing directives, and all
floating values in <float.h> must be constant expressions.
Given this, I'm not sure why the function in C++.
Unless, of course, the real reason is to allow instantiation for
user defined types, for which constant expressions may not be
possible. Looking at it, the values with type T are functions,
and the others not, so this is possibly a more likely
explination.
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "Greg Herlihy" <greghe@pacbell.net>
Date: Wed, 5 Jul 2006 20:31:31 CST Raw View
kanze wrote:
> Greg Herlihy wrote:
.
> The problem is that the same interface is imposed on
> std::numeric_limit<char>::max. And there are a lot of things
> you could do with that if it weren't a function.
>
> The reason std::numeric_limit<>::max is a function is simple:
> there are implementations where it is impossible to determine
> the value until runtime---implementations where runtime options
> may affect it.
The fact that numeric limits are also available as macros in <cfloat>
rules out the possibility of numeric_limits::max() performing any kind
of runtime check. There is only ony limit per program per type. So how
could DBL_MAX and std::numeric_limits<double>::max() ever disagree
without at least one of them being incorrect?
A numeric limit is a superlative property of a specific type and of a
specific program - the greatest (or least) value of that type
encountered in any of the program's possible execution states. Runtime
options simply multiply the number of a program's execution states, but
do not eliminate any that already exist. So the only way to change a
set of limits for a program is to change the program itself - and for
most development environments - that means recompilation.
Greg
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: "kanze" <kanze@gabi-soft.fr>
Date: Thu, 6 Jul 2006 13:24:37 CST Raw View
Greg Herlihy wrote:
> kanze wrote:
> > Greg Herlihy wrote:
> > The problem is that the same interface is imposed on
> > std::numeric_limit<char>::max. And there are a lot of things
> > you could do with that if it weren't a function.
> > The reason std::numeric_limit<>::max is a function is simple:
> > there are implementations where it is impossible to determine
> > the value until runtime---implementations where runtime options
> > may affect it.
> The fact that numeric limits are also available as macros in
> <cfloat> rules out the possibility of numeric_limits::max()
> performing any kind of runtime check.
Not really. The fact that the C standard says that the macros
must be constant expressions does restrict this possibility,
however. (I don't know why, but I was under the impression that
this was not a requirement in C.) The fact that things like
numeric_limits::digits is not a function also pretty much
restrict this possibility.
The fact remains that real machines can change their floating
point representation dynamically, or at least at start-up. How
the C++ implementation copes with the fact that
std::numeric_limits<double>::radix may be either 2 or 16,
according to some bit in a mode register, I don't know, but this
is the actual case for modern IBM mainframes. (The obvious
solution is to just ignore it, and pretend that the processors
work as they always have, and don't support IEEE in option.)
> There is only ony limit per program per type. So how could
> DBL_MAX and std::numeric_limits<double>::max() ever disagree
> without at least one of them being incorrect?
#define DBL_MAX (std::numeric_limits<double>::max())
(That's obviously not a legal definition in C.)
> A numeric limit is a superlative property of a specific type
> and of a specific program - the greatest (or least) value of
> that type encountered in any of the program's possible
> execution states.
I spelled out some of the potential problems in another program.
Changing floating point formats in the middle of program
execution is definitly not for the faint of heart. Deciding
which floating point representation to use at program start-up,
say depending on an environment variable, does seem reasonable
to me, at least in certain contexts. Without the explicit
restrictions that certain values (e.g. FLT_RADIX or
std::numeric_limits<float>::radix) must be integral constant
expressions---in the case of FLT_RADIX, usable in an #if, seems
to exclude this, however.
> Runtime options simply multiply the number of a program's
> execution states, but do not eliminate any that already exist.
True, but certain execution states are not possible. In
particular, for example, on an IBM mainframe, if you are in IBM
native mode, there is no way to represent a floating point value
which would represent the maximum of a IEEE double.
> So the only way to change a set of limits for a
> program is to change the program itself - and for most
> development environments - that means recompilation.
That's not at all true in general. At least at the hardware
level, the limits of an IBM double depend on a bit in a hardware
status word somewhere. (Whether C++ supports such changes is
another question.)
--
James Kanze GABI Software
Conseils en informatique orient e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S mard, 78210 St.-Cyr-l' cole, France, +33 (0)1 30 23 00 34
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Sun, 2 Jul 2006 17:53:15 GMT Raw View
With the Standard as it currently stands, an invocation of the following
function does NOT yield a compile-time constant:
unsigned GetVal()
{
return 72;
}
I'm curious as to why numeric_limits<T>::max() was made to be a function?
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: bop@gmb.dk ("Bo Persson")
Date: Sun, 2 Jul 2006 20:52:42 GMT Raw View
"Frederick Gotham" <fgothamNO@SPAM.com> skrev i meddelandet
news:QDPpg.10947$j7.315242@news.indigo.ie...
>
> With the Standard as it currently stands, an invocation of the
> following
> function does NOT yield a compile-time constant:
>
> unsigned GetVal()
> {
> return 72;
> }
>
>
> I'm curious as to why numeric_limits<T>::max() was made to be a
> function?
>
Because floating point values are not compile time constants. (Think
cross-compiler).
Bo Persson
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: fgothamNO@SPAM.com (Frederick Gotham)
Date: Sun, 2 Jul 2006 23:48:18 GMT Raw View
"Bo Persson" posted:
> Because floating point values are not compile time constants. (Think
> cross-compiler).
Hmm... the following snippet suggests otherwise:
int main()
{
char *p = 25235.25225 ? 0 : 1;
}
--
Frederick Gotham
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]