lcast_precision.hpp 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright Alexander Nasonov & Paul A. Bristow 2006.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. #ifndef BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
  7. #define BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED
  8. #include <climits>
  9. #include <ios>
  10. #include <limits>
  11. #include <boost/config.hpp>
  12. #include <boost/integer_traits.hpp>
  13. namespace boost { namespace detail {
  14. class lcast_abstract_stub {};
  15. // Calculate an argument to pass to std::ios_base::precision from
  16. // lexical_cast. See alternative implementation for broken standard
  17. // libraries in lcast_get_precision below. Keep them in sync, please.
  18. template<class T>
  19. struct lcast_precision
  20. {
  21. using limits = std::numeric_limits<T>;
  22. BOOST_STATIC_CONSTANT(bool, use_default_precision =
  23. !limits::is_specialized || limits::is_exact
  24. );
  25. BOOST_STATIC_CONSTANT(bool, is_specialized_bin =
  26. !use_default_precision &&
  27. limits::radix == 2 && limits::digits > 0
  28. );
  29. BOOST_STATIC_CONSTANT(bool, is_specialized_dec =
  30. !use_default_precision &&
  31. limits::radix == 10 && limits::digits10 > 0
  32. );
  33. BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max =
  34. boost::integer_traits<std::streamsize>::const_max
  35. );
  36. BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U);
  37. static_assert(!is_specialized_dec ||
  38. precision_dec <= streamsize_max + 0UL
  39. , "");
  40. BOOST_STATIC_CONSTANT(unsigned long, precision_bin =
  41. 2UL + limits::digits * 30103UL / 100000UL
  42. );
  43. static_assert(!is_specialized_bin ||
  44. (limits::digits + 0UL < ULONG_MAX / 30103UL &&
  45. precision_bin > limits::digits10 + 0UL &&
  46. precision_bin <= streamsize_max + 0UL)
  47. , "");
  48. BOOST_STATIC_CONSTANT(std::streamsize, value =
  49. is_specialized_bin ? precision_bin
  50. : is_specialized_dec ? precision_dec : 6
  51. );
  52. };
  53. template<class T>
  54. inline std::streamsize lcast_get_precision(T* = 0)
  55. {
  56. return lcast_precision<T>::value;
  57. }
  58. template<class T>
  59. inline void lcast_set_precision(std::ios_base& stream, T*)
  60. {
  61. stream.precision(lcast_get_precision<T>());
  62. }
  63. template<class Source, class Target>
  64. inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
  65. {
  66. std::streamsize const s = lcast_get_precision(static_cast<Source*>(0));
  67. std::streamsize const t = lcast_get_precision(static_cast<Target*>(0));
  68. stream.precision(s > t ? s : t);
  69. }
  70. }}
  71. #endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED