Adam H. Peterson wrote:
Is there a standard way to find the minimum value for a data type? I'm
thinking along the lines of std::numeric_limits<T>::min(). But that
doesn't work for floating point types. I can't use
(-std::numeric_limits<T>::max()) either, because that won't work for
unsigned types (and technically won't work for signed integer types and
others either, although it would probably be "good enough" for them).
Do I need to implement a new template that uses
std::numeric_limits<>::min() and just specialize it for floats/doubles?
Or is this already solved somewhere in the library?
This below I think gives you what you want - however it's impractical
because of the excessive compilation time but ... if compilers were a
little faster, it may actually be practical. However, it's just a toy I
played with that shows computation of numeric constants using templates.
You could easily extend this to compute compile time constants for
things like e, pi, ln 10 nCr, factorial, and even a prime number in such
a way that the constants would be compatible for different machine formats.
Besides that, it's also an interesting compiler stress test.
#include <iostream>
template <typename T, int N>
struct pow_n
{
static const T value = pow_n<T, N-1>::value/2;
};
template <typename T>
struct pow_n<T, 0>
{
static const T value = static_cast<T>( 1 );
};
template <typename T, int N, bool v> struct min_f;
template <typename T, int N>
struct min_f<T,N,true>
{
static const T min_value = pow_n<T,N-1>::value;
static const int min_exponent = N-1;
};
template <typename T, int N, bool v>
struct min_f : min_f<T, N+1, pow_n<T, N>::value/2 == static_cast<T>( 0 ) >
{
};
template<typename T>
struct min_limit
{
static const int min_exponent = min_f<T,0,false>::min_exponent;
static const T min_value = min_f<T,0,false>::min_value;
};
int main()
{
std::cout << "Float\n";
std::cout << min_limit< float >::min_exponent << "\n";
std::cout << min_limit< float >::min_value << "\n";
std::cout << "Double\n";
std::cout << min_limit< double >::min_exponent << "\n";
std::cout << min_limit< double >::min_value << "\n";
};
The code above took 3min 14sec in compilation time on a 800Mhz x86-P3
machine with gcc 3.3.1 with the -ftemplate-depth-10000 flag.
(Obviously miniscule execution time).
g++ -ftemplate-depth-10000 -Wreturn-type -W -Wpointer-arith -pipe -ggdb3
-fcheck-new -fPIC -D_POSIX_THREADS -D_POSIX_THREAD_SAFE_FUNCTIONS
-D_REENTRANT -DACE_HAS_AIO_CALLS
-DBUILD_VERSION=0309262338-i686-uluru-gx86-gianni -DBUILD_ARCH=gx86
-I ./ -I work.gx86 -I
/home/gianni/limbo/asmx/makexs/src/hello_library/code/ qqq.cpp
-o qqq
171.260u 2.830s 3:13.92 89.7% 0+0k 0+0io 3932pf+0w
[gianni@uluru makexs]$ time qqq
Float
149
1.4013e-45
Double
1074
4.94066e-324
0.000u 0.000s 0:00.00 0.0% 0+0k 0+0io 219pf+0w