lcast_precision.hpp 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. #ifndef BOOST_NO_IS_ABSTRACT
  14. // Fix for SF:1358600 - lexical_cast & pure virtual functions & VC 8 STL
  15. #include <boost/type_traits/conditional.hpp>
  16. #include <boost/type_traits/is_abstract.hpp>
  17. #endif
  18. namespace boost { namespace detail {
  19. class lcast_abstract_stub {};
  20. // Calculate an argument to pass to std::ios_base::precision from
  21. // lexical_cast. See alternative implementation for broken standard
  22. // libraries in lcast_get_precision below. Keep them in sync, please.
  23. template<class T>
  24. struct lcast_precision
  25. {
  26. #ifdef BOOST_NO_IS_ABSTRACT
  27. typedef std::numeric_limits<T> limits; // No fix for SF:1358600.
  28. #else
  29. typedef typename boost::conditional<
  30. boost::is_abstract<T>::value
  31. , std::numeric_limits<lcast_abstract_stub>
  32. , std::numeric_limits<T>
  33. >::type limits;
  34. #endif
  35. BOOST_STATIC_CONSTANT(bool, use_default_precision =
  36. !limits::is_specialized || limits::is_exact
  37. );
  38. BOOST_STATIC_CONSTANT(bool, is_specialized_bin =
  39. !use_default_precision &&
  40. limits::radix == 2 && limits::digits > 0
  41. );
  42. BOOST_STATIC_CONSTANT(bool, is_specialized_dec =
  43. !use_default_precision &&
  44. limits::radix == 10 && limits::digits10 > 0
  45. );
  46. BOOST_STATIC_CONSTANT(std::streamsize, streamsize_max =
  47. boost::integer_traits<std::streamsize>::const_max
  48. );
  49. BOOST_STATIC_CONSTANT(unsigned int, precision_dec = limits::digits10 + 1U);
  50. static_assert(!is_specialized_dec ||
  51. precision_dec <= streamsize_max + 0UL
  52. , "");
  53. BOOST_STATIC_CONSTANT(unsigned long, precision_bin =
  54. 2UL + limits::digits * 30103UL / 100000UL
  55. );
  56. static_assert(!is_specialized_bin ||
  57. (limits::digits + 0UL < ULONG_MAX / 30103UL &&
  58. precision_bin > limits::digits10 + 0UL &&
  59. precision_bin <= streamsize_max + 0UL)
  60. , "");
  61. BOOST_STATIC_CONSTANT(std::streamsize, value =
  62. is_specialized_bin ? precision_bin
  63. : is_specialized_dec ? precision_dec : 6
  64. );
  65. };
  66. template<class T>
  67. inline std::streamsize lcast_get_precision(T* = 0)
  68. {
  69. return lcast_precision<T>::value;
  70. }
  71. template<class T>
  72. inline void lcast_set_precision(std::ios_base& stream, T*)
  73. {
  74. stream.precision(lcast_get_precision<T>());
  75. }
  76. template<class Source, class Target>
  77. inline void lcast_set_precision(std::ios_base& stream, Source*, Target*)
  78. {
  79. std::streamsize const s = lcast_get_precision(static_cast<Source*>(0));
  80. std::streamsize const t = lcast_get_precision(static_cast<Target*>(0));
  81. stream.precision(s > t ? s : t);
  82. }
  83. }}
  84. #endif // BOOST_DETAIL_LCAST_PRECISION_HPP_INCLUDED