Given the maximum possible value, how to simply express the space needed to write such number in decimal form as text ?
The real task: logging process ids (pid_t
) with fixed length, using gcc on Linux. It'd be good to have a compile time expression to be used in the std::setw()
iomanipulator.
I have found that linux/threads.h header contains a PID_MAX
value with the maximum pid allocated to a process. So having
#define LENGTH(t) sizeof(#t)-1
the LENGTH(PID_MAX)
would be a compile time expression, but unfortunatelly this number is defined in hexa:
#define PID_MAX 0x8000
My current best solution is a bit oddish
static_cast<int>( ::floor( ::log(PID_MAX)/::log(10) + 1 ) );
But this is calculated runtime and uses functions from math.h
You could do it with a little template meta programming:
//NunLength_interal does the actual calculation.
template <unsigned num>
struct NumLength_internal
{ enum { value = 1 + NumLength_internal<num/10>::value }; };
template <>
struct NumLength_internal<0>
{ enum { value = 0 }; };
//NumLength is a wrapper to handle zero. For zero we want to return
//a length of one as a special case.
template <unsigned num>
struct NumLength
{ enum { value = NumLength_internal<num>::value };};
template <>
struct NumLength<0>
{ enum { value = 1 }; };
This should work for anything now. For example:
cout << NumLength<0>::value << endl; // writes: 1
cout << NumLength<5>::value << endl; // writes: 1
cout << NumLength<10>::value << endl; // writes: 2
cout << NumLength<123>::value << endl; // writes: 3
cout << NumLength<0x8000>::value << endl; // writes: 5
This is all handled at compile time.
Edit: I added another layer to handle the case when the number passed in is zero.