2

Is there a way to find out the number of digits of min/max values of an integral type at compile time so that it's suitable to be placed as a template parameter?

Ideally, there will be an existing solution in, for example, Boost MPL. Failing that I'm looking for some pointers for a hand-coded solution.

Georg Fritzsche
  • 97,545
  • 26
  • 194
  • 236
Alex B
  • 82,554
  • 44
  • 203
  • 280

2 Answers2

9

Is this what you are looking for?

std::numeric_limits<T>::digits10

Number of digits (in decimal base) that can be represented without change.

R Samuel Klatchko
  • 74,869
  • 16
  • 134
  • 187
  • 1
    Note that for the "number of digits of the **min** / **max** values", you might need to add 1, since `::digits10` only indicates the number of digits without change. See [this question](http://stackoverflow.com/questions/5925951/difference-in-digits10-between-gcc-and-msvc). `::digits` (base 2) does not have that issue. – Luis Machuca Jan 15 '12 at 19:15
5

Works with any value you can provide as an unsigned long template argument, in any base:

template<unsigned B, unsigned long N>
struct base_digits_detail {
  enum { result = 1 + base_digits_detail<B, N/B>::result };
};
template<unsigned B>
struct base_digits_detail<B, 0> {
private:
  enum { result = 0 };

  template<unsigned, unsigned long>
  friend class base_digits_detail;
};

template<unsigned B, unsigned long N>
struct base_digits {
  enum { result = base_digits_detail<B, N>::result };
};
template<unsigned B>
struct base_digits<B, 0> {
  enum { result = 1 };
};

Test

#include <climits>
#include <iostream>
int main() {
  std::cout << base_digits<10, 0>::result << '\n';
  std::cout << base_digits<10, 1>::result << '\n';
  std::cout << base_digits<10, 10>::result << '\n';
  std::cout << base_digits<10, 100>::result << '\n';
  std::cout << base_digits<10, 1000>::result << '\n';
  std::cout << base_digits<10, UINT_MAX>::result << '\n';
  std::cout << '\n';
  std::cout << base_digits<8, 0>::result << '\n';
  std::cout << base_digits<8, 01>::result << '\n';
  std::cout << base_digits<8, 010>::result << '\n';
  std::cout << base_digits<8, 0100>::result << '\n';
  std::cout << base_digits<8, 01000>::result << '\n';
  std::cout << base_digits<8, UINT_MAX>::result << '\n';

  return 0;
}

Output

1
1
2
3
4
10

1
1
2
3
4
11