1 // (C) Copyright David Abrahams 2001. Permission to copy, use, modify,
2 // sell and distribute this software is granted provided this
3 // copyright notice appears in all copies. This software is provided
4 // "as is" without express or implied warranty, and with no claim as
5 // to its suitability for any purpose.
7 // Template class is_signed and its documentation is:
8 // (C) Copyright Howard Hinnant 2001. Permission to copy, use, modify,
9 // sell and distribute this software is granted provided this
10 // copyright notice appears in all copies. This software is provided
11 // "as is" without express or implied warranty, and with no claim as
12 // to its suitability for any purpose.
14 // Template class numeric_traits<Number> --
18 // typedef difference_type -- a type used to represent the difference
19 // between any two values of Number.
22 // 1. Not all specializations are supplied
24 // 2. Use of specializations that are not supplied will cause a
27 // 3. Users are free to specialize numeric_traits for any type.
29 // 4. Right now, specializations are only supplied for integer types.
31 // 5. On implementations which do not supply compile-time constants in
32 // std::numeric_limits<>, only specializations for built-in integer types
35 // 6. Handling of numbers whose range of representation is at least as
36 // great as boost::intmax_t can cause some differences to be
37 // unrepresentable in difference_type:
39 // Number difference_type
40 // ------ ---------------
44 // template <class Number> typename numeric_traits<Number>::difference_type
45 // numeric_distance(Number x, Number y)
46 // computes (y - x), attempting to avoid overflows.
49 // See http://www.boost.org for most recent version including documentation.
52 // 11 Feb 2001 - Use BOOST_STATIC_CONSTANT (David Abrahams)
53 // 11 Feb 2001 - Rolled back ineffective Borland-specific code
55 // 10 Feb 2001 - Rolled in supposed Borland fixes from John Maddock, but
56 // not seeing any improvement yet (David Abrahams)
57 // 06 Feb 2001 - Factored if_true out into boost/detail/select_type.hpp
59 // 23 Jan 2001 - Fixed logic of difference_type selection, which was
60 // completely wack. In the process, added digit_traits<>
61 // to compute the number of digits in intmax_t even when
62 // not supplied by numeric_limits<>. (David Abrahams)
63 // 21 Jan 2001 - Created (David Abrahams)
65 #ifndef BOOST_NUMERIC_TRAITS_HPP_DWA20001901
66 # define BOOST_NUMERIC_TRAITS_HPP_DWA20001901
68 # include <boost/config.hpp>
69 # include <boost/cstdint.hpp>
70 # include <boost/static_assert.hpp>
71 # include <boost/type_traits.hpp>
72 # include <boost/detail/select_type.hpp>
73 # include <boost/limits.hpp>
75 namespace boost { namespace detail {
77 // Template class is_signed -- determine whether a numeric type is signed
78 // Requires that T is constructable from the literals -1 and 0. Compile-time
79 // error results if that requirement is not met (and thus signedness is not
80 // likely to have meaning for that type).
81 template <class Number>
84 #if defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) || defined(BOOST_MSVC)
85 BOOST_STATIC_CONSTANT(bool, value = (Number(-1) < Number(0)));
87 BOOST_STATIC_CONSTANT(bool, value = std::numeric_limits<Number>::is_signed);
91 # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
92 // digit_traits - compute the number of digits in a built-in integer
93 // type. Needed for implementations on which numeric_limits is not specialized
94 // for intmax_t (e.g. VC6).
95 template <bool is_specialized> struct digit_traits_select;
97 // numeric_limits is specialized; just select that version of digits
98 template <> struct digit_traits_select<true>
100 template <class T> struct traits
102 BOOST_STATIC_CONSTANT(int, digits = std::numeric_limits<T>::digits);
106 // numeric_limits is not specialized; compute digits from sizeof(T)
107 template <> struct digit_traits_select<false>
109 template <class T> struct traits
111 BOOST_STATIC_CONSTANT(int, digits = (
112 sizeof(T) * std::numeric_limits<unsigned char>::digits
113 - (is_signed<T>::value ? 1 : 0))
118 // here's the "usable" template
119 template <class T> struct digit_traits
121 typedef digit_traits_select<
122 ::std::numeric_limits<T>::is_specialized> selector;
123 typedef typename selector::template traits<T> traits;
124 BOOST_STATIC_CONSTANT(int, digits = traits::digits);
128 // Template class integer_traits<Integer> -- traits of various integer types
129 // This should probably be rolled into boost::integer_traits one day, but I
130 // need it to work without <limits>
131 template <class Integer>
132 struct integer_traits
134 # ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
136 typedef Integer integer_type;
137 typedef std::numeric_limits<integer_type> x;
139 // for some reason, MSVC asserts when it shouldn't unless we make these
141 BOOST_STATIC_CONSTANT(bool, is_integer = x::is_integer);
142 BOOST_STATIC_CONSTANT(bool, is_specialized = x::is_specialized);
144 BOOST_STATIC_ASSERT(is_integer);
145 BOOST_STATIC_ASSERT(is_specialized);
149 if_true<(int(x::is_signed)
150 && (!int(x::is_bounded)
151 // digits is the number of no-sign bits
152 || (int(x::digits) + 1 >= digit_traits<boost::intmax_t>::digits)))>::template then<
155 typename if_true<(int(x::digits) + 1 < digit_traits<signed int>::digits)>::template then<
158 typename if_true<(int(x::digits) + 1 < digit_traits<signed long>::digits)>::template then<
163 >::type>::type>::type difference_type;
165 BOOST_STATIC_ASSERT(boost::is_integral<Integer>::value);
168 if_true<(sizeof(Integer) >= sizeof(intmax_t))>::template then<
170 typename if_true<(is_signed<Integer>::value)>::template then<
175 typename if_true<(sizeof(Integer) < sizeof(std::ptrdiff_t))>::template then<
179 >::type difference_type;
183 // Right now, only supports integers, but should be expanded.
184 template <class Number>
185 struct numeric_traits
187 typedef typename integer_traits<Number>::difference_type difference_type;
190 template <class Number>
191 typename numeric_traits<Number>::difference_type numeric_distance(Number x, Number y)
193 typedef typename numeric_traits<Number>::difference_type difference_type;
194 return difference_type(y) - difference_type(x);
198 #endif // BOOST_NUMERIC_TRAITS_HPP_DWA20001901