10 #if !defined(SG14_CONST_INTEGER_H) 11 #define SG14_CONST_INTEGER_H 1 13 #include <sg14/auxiliary/numeric.h> 14 #include <sg14/bits/common.h> 18 #if defined(SG14_EXCEPTIONS_ENABLED) 23 namespace _const_integer_impl {
30 constexpr std::intmax_t combine(
int, std::intmax_t p)
36 constexpr std::intmax_t combine(
int base, std::intmax_t val,
int p0, TT... pp)
38 return combine(base, val * base + p0, pp...);
41 constexpr
int parse_dec(
char C)
43 #if defined(SG14_EXCEPTIONS_ENABLED) 44 return (C>=
'0' && C<=
'9')
46 :
throw std::out_of_range(
"only decimal digits are allowed");
52 constexpr
int parse_hex(
char C) {
53 return (C >=
'0' && C <=
'9')
55 : (C >=
'a' && C <=
'f')
57 : (C >=
'A' && C <=
'F')
59 #if defined(SG14_EXCEPTIONS_ENABLED) 60 :
throw std::out_of_range(
"only decimal digits are allowed")
67 template<
char... Digits>
68 struct digits_to_integral {
69 static constexpr std::intmax_t value = combine(10, 0, parse_dec(Digits)...);
72 template<
char... Digits>
73 struct digits_to_integral<'0', 'x', Digits...> {
74 static constexpr std::intmax_t value = combine(16, 0, parse_hex(Digits)...);
77 template<
char... Digits>
78 struct digits_to_integral<'0', 'X', Digits...> {
79 static constexpr std::intmax_t value = combine(16, 0, parse_hex(Digits)...);
96 int Digits = used_bits(Value),
97 int Exponent = trailing_bits(Value)>
100 using value_type = Integral;
101 static constexpr value_type value = Value;
104 constexpr
explicit operator T()
const {
return value; }
106 static constexpr
int digits = Digits;
108 digits == used_bits(Value),
109 "defaulted non-type template parameters should not be specified explicitly");
111 static constexpr
int exponent = Exponent;
113 exponent == trailing_bits(Value),
114 "defaulted non-type template parameters should not be specified explicitly");
120 namespace _const_integer_impl {
121 template<
class Lhs,
class Rhs,
class Type>
125 class LhsIntegral, LhsIntegral LhsValue,
int LhsDigits,
int LhsExponent,
126 class RhsIntegral, RhsIntegral RhsValue,
int RhsDigits,
int RhsExponent,
129 const_integer<LhsIntegral, LhsValue, LhsDigits, LhsExponent>,
130 const_integer<RhsIntegral, RhsValue, RhsDigits, RhsExponent>,
136 class LhsIntegral, LhsIntegral LhsValue,
int LhsDigits,
int LhsExponent,
140 const_integer<LhsIntegral, LhsValue, LhsDigits, LhsExponent>,
148 class RhsIntegral, RhsIntegral RhsValue,
int RhsDigits,
int RhsExponent,
152 const_integer<RhsIntegral, RhsValue, RhsDigits, RhsExponent>,
161 class RhsIntegral, RhsIntegral RhsValue,
int RhsDigits,
int RhsExponent,
162 class = _impl::enable_if_t<std::is_integral<Lhs>::value>>
163 constexpr
auto operate(
167 -> decltype(op(lhs, RhsValue)) {
168 return op(lhs, RhsValue);
174 class LhsIntegral, LhsIntegral LhsValue,
int LhsDigits,
int LhsExponent,
176 class = _impl::enable_if_t<std::is_integral<Rhs>::value,
int>>
177 constexpr
auto operate(
181 -> decltype(op(LhsValue, rhs)) {
182 return op(LhsValue, rhs);
188 class LhsIntegral, LhsIntegral LhsValue,
int LhsDigits,
int LhsExponent,
189 class RhsIntegral, RhsIntegral RhsValue,
int RhsDigits,
int RhsExponent>
190 constexpr
auto operate(
194 -> decltype(const_integer<_impl::op_result<Operator, LhsIntegral, RhsIntegral>, Operator()(LhsValue, RhsValue)>{}) {
199 template<class Lhs, class Rhs, typename _const_integer_impl::enable_if_op<Lhs, Rhs, int>::type dummy = 0>
200 constexpr
auto operator+(
const Lhs& lhs,
const Rhs& rhs)
201 -> decltype(_const_integer_impl::operate(lhs, rhs, _impl::add_tag))
203 return _const_integer_impl::operate(lhs, rhs, _impl::add_tag);
206 template<class Lhs, class Rhs, typename _const_integer_impl::enable_if_op<Lhs, Rhs, int>::type dummy = 0>
207 constexpr
auto operator-(
const Lhs& lhs,
const Rhs& rhs)
208 -> decltype(_const_integer_impl::operate(lhs, rhs, _impl::subtract_tag))
210 return _const_integer_impl::operate(lhs, rhs, _impl::subtract_tag);
213 template<class Lhs, class Rhs, typename _const_integer_impl::enable_if_op<Lhs, Rhs, int>::type dummy = 0>
214 constexpr
auto operator*(
const Lhs& lhs,
const Rhs& rhs)
215 -> decltype(_const_integer_impl::operate(lhs, rhs, _impl::multiply_tag))
217 return _const_integer_impl::operate(lhs, rhs, _impl::multiply_tag);
220 template<class Lhs, class Rhs, typename _const_integer_impl::enable_if_op<Lhs, Rhs, int>::type dummy = 0>
221 constexpr
auto operator/(
const Lhs& lhs,
const Rhs& rhs)
222 -> decltype(_const_integer_impl::operate(lhs, rhs, _impl::divide_tag))
224 return _const_integer_impl::operate(lhs, rhs, _impl::divide_tag);
230 namespace _const_integer_impl {
234 class LhsIntegral, LhsIntegral LhsValue,
int LhsDigits,
int LhsExponent,
235 class RhsIntegral, RhsIntegral RhsValue,
int RhsDigits,
int RhsExponent>
236 constexpr
auto compare(
240 -> decltype(op(LhsValue, RhsValue))
242 return op(LhsValue, RhsValue);
246 template<class Lhs, class Rhs, typename _const_integer_impl::enable_if_op<Lhs, Rhs, int>::type dummy = 0>
247 constexpr
auto operator==(
const Lhs& lhs,
const Rhs& rhs)
248 -> decltype(_const_integer_impl::compare(lhs, rhs, _impl::equal_tag))
250 return _const_integer_impl::compare(lhs, rhs, _impl::equal_tag);
253 #if ! defined(_MSC_VER) || (_MSC_VER > 1900) 254 template<
class RhsIntegral, RhsIntegral RhsValue>
266 struct is_const_integer : std::false_type {};
268 template<
class Integral, Integral Value>
269 struct is_const_integer<const_integer<Integral, Value>> : std::true_type {};
277 template<
char... Digits>
278 constexpr
auto operator "" _c()
279 -> const_integer<std::intmax_t, _const_integer_impl::digits_to_integral<Digits...>::value>
289 template<
class Integral, Integral Value,
int Digits,
int Zeros,
class Rhs>
290 struct common_type<sg14::
const_integer<Integral, Value, Digits, Zeros>, Rhs>
291 : common_type<Integral, Rhs> {
294 template<
class Lhs,
class Integral, Integral Value,
int Digits,
int Zeros>
295 struct common_type<Lhs, sg14::
const_integer<Integral, Value, Digits, Zeros>>
296 : common_type<Lhs, Integral> {
302 template<
class Integral, Integral Value,
int Digits,
int Zeros>
303 struct numeric_limits<sg14::
const_integer<Integral, Value, Digits, Zeros>>
304 : numeric_limits<Integral> {
306 static constexpr
int digits = Digits;
310 #endif // SG14_CONST_INTEGER_H
a compile-time-only integer type like a std::integral_constant with arithmetic support ...
Definition: const_integer.h:98
study group 14 of the C++ working group
Definition: const_integer.h:22