lcast_precision.hpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  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. namespace boost { namespace detail {
  13. // Calculate an argument to pass to std::ios_base::precision from
  14. // lexical_cast.
  15. template<class T>
  16. struct lcast_precision
  17. {
  18. using limits = std::numeric_limits<T>;
  19. static constexpr bool use_default_precision =
  20. !limits::is_specialized || limits::is_exact
  21. ;
  22. static constexpr bool is_specialized_bin =
  23. !use_default_precision &&
  24. limits::radix == 2 && limits::digits > 0
  25. ;
  26. static constexpr bool is_specialized_dec =
  27. !use_default_precision &&
  28. limits::radix == 10 && limits::digits10 > 0
  29. ;
  30. static constexpr std::streamsize streamsize_max =
  31. (std::numeric_limits<std::streamsize>::max)()
  32. ;
  33. static constexpr unsigned int precision_dec = limits::digits10 + 1U;
  34. static_assert(!is_specialized_dec ||
  35. precision_dec <= streamsize_max + 0UL
  36. , "");
  37. static constexpr unsigned long precision_bin =
  38. 2UL + limits::digits * 30103UL / 100000UL
  39. ;
  40. static_assert(!is_specialized_bin ||
  41. (limits::digits + 0UL < ULONG_MAX / 30103UL &&
  42. precision_bin > limits::digits10 + 0UL &&
  43. precision_bin <= streamsize_max + 0UL)
  44. , "");
  45. static constexpr std::streamsize value =
  46. is_specialized_bin ? precision_bin
  47. : is_specialized_dec ? precision_dec : 6
  48. ;
  49. };
  50. template<class T>
  51. inline void lcast_set_precision(std::ios_base& stream, T*)
  52. {
  53. stream.precision(lcast_precision<T>::value);
  54. }
  55. template<class Source, class Target>
  56. inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
  57. {
  58. std::streamsize const s = lcast_precision<Source>::value;
  59. std::streamsize const t = lcast_precision<Target*>::value;
  60. stream.precision(s > t ? s : t);
  61. }
  62. }}
  63. #endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED