traits.hpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. /* boost random/traits.hpp header file
  2. *
  3. * Copyright John Maddock 2015
  4. * Distributed under the Boost Software License, Version 1.0. (See
  5. * accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * See http://www.boost.org for most recent version including documentation.
  9. *
  10. * These traits classes serve two purposes: they are designed to mostly
  11. * work out of the box for multiprecision types (ie number types that are
  12. * C++ class types and not integers or floats from type-traits point of view),
  13. * they are also a potential point of specialization for user-defined
  14. * number types.
  15. *
  16. * $Id$
  17. */
  18. #ifndef BOOST_RANDOM_TRAITS_HPP
  19. #define BOOST_RANDOM_TRAITS_HPP
  20. #include <boost/type_traits/integral_constant.hpp>
  21. #include <boost/type_traits/is_signed.hpp>
  22. #include <boost/type_traits/is_integral.hpp>
  23. #include <boost/type_traits/make_unsigned.hpp>
  24. #include <limits>
  25. namespace boost {
  26. namespace random {
  27. namespace traits {
  28. // \cond show_private
  29. template <class T, bool intrinsic>
  30. struct make_unsigned_imp
  31. {
  32. typedef typename boost::make_unsigned<T>::type type;
  33. };
  34. template <class T>
  35. struct make_unsigned_imp<T, false>
  36. {
  37. BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
  38. BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_signed == false);
  39. BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true);
  40. typedef T type;
  41. };
  42. // \endcond
  43. /** \brief Converts the argument type T to an unsigned type.
  44. *
  45. * This trait has a single member `type` which is the unsigned type corresponding to T.
  46. * Note that
  47. * if T is signed, then member `type` *should define a type with one more bit precision than T*. For built-in
  48. * types this trait defaults to `boost::make_unsigned<T>::type`. For user defined types it simply asserts that
  49. * the argument type T is an unsigned integer (using std::numeric_limits).
  50. * User defined specializations may be provided for other cases.
  51. */
  52. template <class T>
  53. struct make_unsigned
  54. // \cond show_private
  55. : public make_unsigned_imp < T, boost::is_integral<T>::value >
  56. // \endcond
  57. {};
  58. // \cond show_private
  59. template <class T, bool intrinsic>
  60. struct make_unsigned_or_unbounded_imp
  61. {
  62. typedef typename boost::make_unsigned<T>::type type;
  63. };
  64. template <class T>
  65. struct make_unsigned_or_unbounded_imp<T, false>
  66. {
  67. BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized);
  68. BOOST_STATIC_ASSERT((std::numeric_limits<T>::is_signed == false) || (std::numeric_limits<T>::is_bounded == false));
  69. BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true);
  70. typedef T type;
  71. };
  72. // \endcond
  73. /** \brief Converts the argument type T to either an unsigned type or an unbounded integer type.
  74. *
  75. * This trait has a single member `type` which is either the unsigned type corresponding to T or an unbounded
  76. * integer type. This trait is used to generate types suitable for the calculation of a range: as a result
  77. * if T is signed, then member `type` *should define a type with one more bit precision than T*. For built-in
  78. * types this trait defaults to `boost::make_unsigned<T>::type`. For user defined types it simply asserts that
  79. * the argument type T is either an unbounded integer, or an unsigned one (using std::numeric_limits).
  80. * User defined specializations may be provided for other cases.
  81. */
  82. template <class T>
  83. struct make_unsigned_or_unbounded
  84. // \cond show_private
  85. : public make_unsigned_or_unbounded_imp < T, boost::is_integral<T>::value >
  86. // \endcond
  87. {};
  88. /** \brief Traits class that indicates whether type T is an integer
  89. */
  90. template <class T>
  91. struct is_integral
  92. : public integral_constant<bool, boost::is_integral<T>::value || (std::numeric_limits<T>::is_integer)>
  93. {};
  94. /** \brief Traits class that indicates whether type T is a signed integer
  95. */
  96. template <class T> struct is_signed
  97. : public integral_constant<bool, boost::is_signed<T>::value || (std::numeric_limits<T>::is_specialized && std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed)>
  98. {};
  99. }
  100. }
  101. }
  102. #endif