OK, let's see. The return values of numeric_limits::min() and max() are not compile-time constants from the language point of view, for the simple reason that function return values never are. This is not a performance problem, since these functions will most definitely be inlined by any even halfway decent compiler, but it matters because compile-time constants are required in some circumstances. In particular, you can't use min() and max() as array bounds or as non-type template parameters.
There are some very good reasons to make them functions. Peculiarly enough, one of those reasons is performance. Consider:
Code:
// This is <limits>
template <>
struct numeric_limits<float>
{
static float min() { return <minimal floating point value>; }
};
This is what a specialization of numeric_limits looks like in the standard. The compiler, seeing a call of min(), would simply inline the function and find out that it's dealing with a simple literal, opening up a lot of new optimization opportunities.
Let's examine the possibilities if it's a static constant variable.
Code:
// This is <limits>
template <>
struct numeric_limits<float>
{
static const float min = <minimal floating point value>;
};
Nope, that's an error. Inline initialization is only allowed for integral static constants.
Code:
// This is <limits>
template <>
struct numeric_limits<float>
{
static const float min;
};
template <>
const float numeric_limits<float>::min = <minimal floating point value>;
Nope, that's another error. Specifically, you'll get linker errors from this symbol.
How about this then?
Code:
// This is <limits>
template <>
struct numeric_limits<float>
{
static const float min;
};
// This is limits.cpp, a file linked into the compiler's precompiled standard library.
template <>
const float numeric_limits<float>::min = <minimal floating point value>;
Ah yes, that works. Only, now the constant value is no longer accessible to the compiler for further optimization. Oops.
OK, so a compiler that does cross-module optimization might be able to optimize this. If, that is, you're linking against a static version of the runtime. Definitely not if you're linking against a dynamic version.
So by converting the function to a static constant, in the belief that perhaps this is faster, you've actually made it slower.
Here's the good news: C++0x introduces the constexpr keyword, which forces the compiler to evaluate simple functions at compile time if possible. Thus, the result becomes a proper compiler-time constant expression, and you get the best of both worlds.