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 19 #ifndef BOOST_RANDOM_TRAITS_HPP 20 #define BOOST_RANDOM_TRAITS_HPP 21 22 #include <boost/type_traits/integral_constant.hpp> 23 #include <boost/type_traits/is_signed.hpp> 24 #include <boost/type_traits/is_integral.hpp> 25 #include <boost/type_traits/make_unsigned.hpp> 26 #include <limits> 27 28 namespace boost { 29 namespace random { 30 namespace traits { 31 // \cond show_private 32 template <class T, bool intrinsic> 33 struct make_unsigned_imp 34 { 35 typedef typename boost::make_unsigned<T>::type type; 36 }; 37 template <class T> 38 struct make_unsigned_imp<T, false> 39 { 40 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized); 41 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_signed == false); 42 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true); 43 typedef T type; 44 }; 45 // \endcond 46 /** \brief Converts the argument type T to an unsigned type. 47 * 48 * This trait has a single member `type` which is the unsigned type corresponding to T. 49 * Note that 50 * if T is signed, then member `type` *should define a type with one more bit precision than T*. For built-in 51 * types this trait defaults to `boost::make_unsigned<T>::type`. For user defined types it simply asserts that 52 * the argument type T is an unsigned integer (using std::numeric_limits). 53 * User defined specializations may be provided for other cases. 54 */ 55 template <class T> 56 struct make_unsigned 57 // \cond show_private 58 : public make_unsigned_imp < T, boost::is_integral<T>::value > 59 // \endcond 60 {}; 61 // \cond show_private 62 template <class T, bool intrinsic> 63 struct make_unsigned_or_unbounded_imp 64 { 65 typedef typename boost::make_unsigned<T>::type type; 66 }; 67 template <class T> 68 struct make_unsigned_or_unbounded_imp<T, false> 69 { 70 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_specialized); 71 BOOST_STATIC_ASSERT((std::numeric_limits<T>::is_signed == false) || (std::numeric_limits<T>::is_bounded == false)); 72 BOOST_STATIC_ASSERT(std::numeric_limits<T>::is_integer == true); 73 typedef T type; 74 }; 75 // \endcond 76 /** \brief Converts the argument type T to either an unsigned type or an unbounded integer type. 77 * 78 * This trait has a single member `type` which is either the unsigned type corresponding to T or an unbounded 79 * integer type. This trait is used to generate types suitable for the calculation of a range: as a result 80 * if T is signed, then member `type` *should define a type with one more bit precision than T*. For built-in 81 * types this trait defaults to `boost::make_unsigned<T>::type`. For user defined types it simply asserts that 82 * the argument type T is either an unbounded integer, or an unsigned one (using std::numeric_limits). 83 * User defined specializations may be provided for other cases. 84 */ 85 template <class T> 86 struct make_unsigned_or_unbounded 87 // \cond show_private 88 : public make_unsigned_or_unbounded_imp < T, boost::is_integral<T>::value > 89 // \endcond 90 {}; 91 /** \brief Traits class that indicates whether type T is an integer 92 */ 93 template <class T> 94 struct is_integral 95 : public integral_constant<bool, boost::is_integral<T>::value || (std::numeric_limits<T>::is_integer)> 96 {}; 97 /** \brief Traits class that indicates whether type T is a signed integer 98 */ 99 template <class T> struct is_signed 100 : 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)> 101 {}; 102 103 } 104 } 105 } 106 107 #endif 108