Skip to content

Commit 0bc45a2

Browse files
authored
Merge pull request #1220 from cppalliance/1203
Simplify `numeric_limits` and fix ODR violations
2 parents c6dd35a + c591ec5 commit 0bc45a2

File tree

12 files changed

+430
-139
lines changed

12 files changed

+430
-139
lines changed

include/boost/decimal/decimal128_t.hpp

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2228,22 +2228,12 @@ constexpr auto scalbnd128(decimal128_t num, const int expval) noexcept -> decima
22282228
return scalblnd128(num, static_cast<long>(expval));
22292229
}
22302230

2231-
} //namespace decimal
2232-
} //namespace boost
2233-
2234-
namespace std {
2231+
namespace detail {
22352232

2236-
template<>
2237-
#ifdef _MSC_VER
2238-
class numeric_limits<boost::decimal::decimal128_t>
2239-
#else
2240-
struct numeric_limits<boost::decimal::decimal128_t>
2241-
#endif
2233+
template <bool>
2234+
class numeric_limits_impl128
22422235
{
2243-
2244-
#ifdef _MSC_VER
2245-
public:
2246-
#endif
2236+
public:
22472237

22482238
static constexpr bool is_specialized = true;
22492239
static constexpr bool is_signed = true;
@@ -2271,7 +2261,7 @@ struct numeric_limits<boost::decimal::decimal128_t>
22712261
static constexpr int min_exponent10 = min_exponent;
22722262
static constexpr int max_exponent = 6144;
22732263
static constexpr int max_exponent10 = max_exponent;
2274-
static constexpr bool traps = numeric_limits<std::uint64_t>::traps;
2264+
static constexpr bool traps = std::numeric_limits<std::uint64_t>::traps;
22752265
static constexpr bool tinyness_before = true;
22762266

22772267
// Member functions
@@ -2286,6 +2276,59 @@ struct numeric_limits<boost::decimal::decimal128_t>
22862276
static constexpr auto denorm_min () -> boost::decimal::decimal128_t { return {1, boost::decimal::detail::etiny_v<boost::decimal::decimal128_t>}; }
22872277
};
22882278

2279+
#if !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
2280+
2281+
template <bool b> constexpr bool numeric_limits_impl128<b>::is_specialized;
2282+
template <bool b> constexpr bool numeric_limits_impl128<b>::is_signed;
2283+
template <bool b> constexpr bool numeric_limits_impl128<b>::is_integer;
2284+
template <bool b> constexpr bool numeric_limits_impl128<b>::is_exact;
2285+
template <bool b> constexpr bool numeric_limits_impl128<b>::has_infinity;
2286+
template <bool b> constexpr bool numeric_limits_impl128<b>::has_quiet_NaN;
2287+
template <bool b> constexpr bool numeric_limits_impl128<b>::has_signaling_NaN;
2288+
2289+
// These members were deprecated in C++23
2290+
#if ((!defined(_MSC_VER) && (__cplusplus <= 202002L)) || (defined(_MSC_VER) && (_MSVC_LANG <= 202002L)))
2291+
template <bool b> constexpr std::float_denorm_style numeric_limits_impl128<b>::has_denorm;
2292+
template <bool b> constexpr bool numeric_limits_impl128<b>::has_denorm_loss;
2293+
#endif
2294+
2295+
template <bool b> constexpr std::float_round_style numeric_limits_impl128<b>::round_style;
2296+
template <bool b> constexpr bool numeric_limits_impl128<b>::is_iec559;
2297+
template <bool b> constexpr bool numeric_limits_impl128<b>::is_bounded;
2298+
template <bool b> constexpr bool numeric_limits_impl128<b>::is_modulo;
2299+
template <bool b> constexpr int numeric_limits_impl128<b>::digits;
2300+
template <bool b> constexpr int numeric_limits_impl128<b>::digits10;
2301+
template <bool b> constexpr int numeric_limits_impl128<b>::max_digits10;
2302+
template <bool b> constexpr int numeric_limits_impl128<b>::radix;
2303+
template <bool b> constexpr int numeric_limits_impl128<b>::min_exponent;
2304+
template <bool b> constexpr int numeric_limits_impl128<b>::min_exponent10;
2305+
template <bool b> constexpr int numeric_limits_impl128<b>::max_exponent;
2306+
template <bool b> constexpr int numeric_limits_impl128<b>::max_exponent10;
2307+
template <bool b> constexpr bool numeric_limits_impl128<b>::traps;
2308+
template <bool b> constexpr bool numeric_limits_impl128<b>::tinyness_before;
2309+
2310+
#endif // !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
2311+
2312+
} // namespace detail
2313+
2314+
} //namespace decimal
2315+
} //namespace boost
2316+
2317+
namespace std {
2318+
2319+
#ifdef __clang__
2320+
# pragma clang diagnostic push
2321+
# pragma clang diagnostic ignored "-Wmismatched-tags"
2322+
#endif
2323+
2324+
template <>
2325+
class numeric_limits<boost::decimal::decimal128_t> :
2326+
public boost::decimal::detail::numeric_limits_impl128<true> {};
2327+
2328+
#ifdef __clang__
2329+
# pragma clang diagnostic pop
2330+
#endif
2331+
22892332
} //namespace std
22902333

22912334
#include <boost/decimal/charconv.hpp>

include/boost/decimal/decimal32_t.hpp

Lines changed: 58 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2297,22 +2297,12 @@ constexpr auto copysignd32(decimal32_t mag, const decimal32_t sgn) noexcept -> d
22972297
return mag;
22982298
}
22992299

2300-
} // namespace decimal
2301-
} // namespace boost
2302-
2303-
namespace std {
2300+
namespace detail {
23042301

2305-
template <>
2306-
#ifdef _MSC_VER
2307-
class numeric_limits<boost::decimal::decimal32_t>
2308-
#else
2309-
struct numeric_limits<boost::decimal::decimal32_t>
2310-
#endif
2302+
template <bool>
2303+
class numeric_limits_impl32
23112304
{
2312-
2313-
#ifdef _MSC_VER
23142305
public:
2315-
#endif
23162306

23172307
static constexpr bool is_specialized = true;
23182308
static constexpr bool is_signed = true;
@@ -2340,7 +2330,7 @@ struct numeric_limits<boost::decimal::decimal32_t>
23402330
static constexpr int min_exponent10 = min_exponent;
23412331
static constexpr int max_exponent = 96;
23422332
static constexpr int max_exponent10 = max_exponent;
2343-
static constexpr bool traps = numeric_limits<std::uint32_t>::traps;
2333+
static constexpr bool traps = std::numeric_limits<std::uint32_t>::traps;
23442334
static constexpr bool tinyness_before = true;
23452335

23462336
// Member functions
@@ -2353,8 +2343,62 @@ struct numeric_limits<boost::decimal::decimal32_t>
23532343
static constexpr auto quiet_NaN () -> boost::decimal::decimal32_t { return boost::decimal::from_bits(boost::decimal::detail::d32_nan_mask); }
23542344
static constexpr auto signaling_NaN() -> boost::decimal::decimal32_t { return boost::decimal::from_bits(boost::decimal::detail::d32_snan_mask); }
23552345
static constexpr auto denorm_min () -> boost::decimal::decimal32_t { return {1, boost::decimal::detail::etiny}; }
2346+
23562347
};
23572348

2349+
#if !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
2350+
2351+
template <bool b> constexpr bool numeric_limits_impl32<b>::is_specialized;
2352+
template <bool b> constexpr bool numeric_limits_impl32<b>::is_signed;
2353+
template <bool b> constexpr bool numeric_limits_impl32<b>::is_integer;
2354+
template <bool b> constexpr bool numeric_limits_impl32<b>::is_exact;
2355+
template <bool b> constexpr bool numeric_limits_impl32<b>::has_infinity;
2356+
template <bool b> constexpr bool numeric_limits_impl32<b>::has_quiet_NaN;
2357+
template <bool b> constexpr bool numeric_limits_impl32<b>::has_signaling_NaN;
2358+
2359+
// These members were deprecated in C++23
2360+
#if ((!defined(_MSC_VER) && (__cplusplus <= 202002L)) || (defined(_MSC_VER) && (_MSVC_LANG <= 202002L)))
2361+
template <bool b> constexpr std::float_denorm_style numeric_limits_impl32<b>::has_denorm;
2362+
template <bool b> constexpr bool numeric_limits_impl32<b>::has_denorm_loss;
2363+
#endif
2364+
2365+
template <bool b> constexpr std::float_round_style numeric_limits_impl32<b>::round_style;
2366+
template <bool b> constexpr bool numeric_limits_impl32<b>::is_iec559;
2367+
template <bool b> constexpr bool numeric_limits_impl32<b>::is_bounded;
2368+
template <bool b> constexpr bool numeric_limits_impl32<b>::is_modulo;
2369+
template <bool b> constexpr int numeric_limits_impl32<b>::digits;
2370+
template <bool b> constexpr int numeric_limits_impl32<b>::digits10;
2371+
template <bool b> constexpr int numeric_limits_impl32<b>::max_digits10;
2372+
template <bool b> constexpr int numeric_limits_impl32<b>::radix;
2373+
template <bool b> constexpr int numeric_limits_impl32<b>::min_exponent;
2374+
template <bool b> constexpr int numeric_limits_impl32<b>::min_exponent10;
2375+
template <bool b> constexpr int numeric_limits_impl32<b>::max_exponent;
2376+
template <bool b> constexpr int numeric_limits_impl32<b>::max_exponent10;
2377+
template <bool b> constexpr bool numeric_limits_impl32<b>::traps;
2378+
template <bool b> constexpr bool numeric_limits_impl32<b>::tinyness_before;
2379+
2380+
#endif // !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
2381+
2382+
} // namespace detail
2383+
2384+
} // namespace decimal
2385+
} // namespace boost
2386+
2387+
namespace std {
2388+
2389+
#ifdef __clang__
2390+
# pragma clang diagnostic push
2391+
# pragma clang diagnostic ignored "-Wmismatched-tags"
2392+
#endif
2393+
2394+
template <>
2395+
class numeric_limits<boost::decimal::decimal32_t> :
2396+
public boost::decimal::detail::numeric_limits_impl32<true> {};
2397+
2398+
#ifdef __clang__
2399+
# pragma clang diagnostic pop
2400+
#endif
2401+
23582402
} // Namespace std
23592403

23602404
#include <boost/decimal/charconv.hpp>

include/boost/decimal/decimal64_t.hpp

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2192,22 +2192,12 @@ constexpr auto copysignd64(decimal64_t mag, const decimal64_t sgn) noexcept -> d
21922192
return mag;
21932193
}
21942194

2195-
} //namespace decimal
2196-
} //namespace boost
2197-
2198-
namespace std {
2195+
namespace detail {
21992196

2200-
template <>
2201-
#ifdef _MSC_VER
2202-
class numeric_limits<boost::decimal::decimal64_t>
2203-
#else
2204-
struct numeric_limits<boost::decimal::decimal64_t>
2205-
#endif
2197+
template <bool>
2198+
class numeric_limits_impl64
22062199
{
2207-
2208-
#ifdef _MSC_VER
2209-
public:
2210-
#endif
2200+
public:
22112201

22122202
static constexpr bool is_specialized = true;
22132203
static constexpr bool is_signed = true;
@@ -2235,7 +2225,7 @@ struct numeric_limits<boost::decimal::decimal64_t>
22352225
static constexpr int min_exponent10 = min_exponent;
22362226
static constexpr int max_exponent = 384;
22372227
static constexpr int max_exponent10 = max_exponent;
2238-
static constexpr bool traps = numeric_limits<std::uint64_t>::traps;
2228+
static constexpr bool traps = std::numeric_limits<std::uint64_t>::traps;
22392229
static constexpr bool tinyness_before = true;
22402230

22412231
// Member functions
@@ -2250,6 +2240,59 @@ struct numeric_limits<boost::decimal::decimal64_t>
22502240
static constexpr auto denorm_min () -> boost::decimal::decimal64_t { return {1, boost::decimal::detail::etiny_v<boost::decimal::decimal64_t>}; }
22512241
};
22522242

2243+
#if !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
2244+
2245+
template <bool b> constexpr bool numeric_limits_impl64<b>::is_specialized;
2246+
template <bool b> constexpr bool numeric_limits_impl64<b>::is_signed;
2247+
template <bool b> constexpr bool numeric_limits_impl64<b>::is_integer;
2248+
template <bool b> constexpr bool numeric_limits_impl64<b>::is_exact;
2249+
template <bool b> constexpr bool numeric_limits_impl64<b>::has_infinity;
2250+
template <bool b> constexpr bool numeric_limits_impl64<b>::has_quiet_NaN;
2251+
template <bool b> constexpr bool numeric_limits_impl64<b>::has_signaling_NaN;
2252+
2253+
// These members were deprecated in C++23
2254+
#if ((!defined(_MSC_VER) && (__cplusplus <= 202002L)) || (defined(_MSC_VER) && (_MSVC_LANG <= 202002L)))
2255+
template <bool b> constexpr std::float_denorm_style numeric_limits_impl64<b>::has_denorm;
2256+
template <bool b> constexpr bool numeric_limits_impl64<b>::has_denorm_loss;
2257+
#endif
2258+
2259+
template <bool b> constexpr std::float_round_style numeric_limits_impl64<b>::round_style;
2260+
template <bool b> constexpr bool numeric_limits_impl64<b>::is_iec559;
2261+
template <bool b> constexpr bool numeric_limits_impl64<b>::is_bounded;
2262+
template <bool b> constexpr bool numeric_limits_impl64<b>::is_modulo;
2263+
template <bool b> constexpr int numeric_limits_impl64<b>::digits;
2264+
template <bool b> constexpr int numeric_limits_impl64<b>::digits10;
2265+
template <bool b> constexpr int numeric_limits_impl64<b>::max_digits10;
2266+
template <bool b> constexpr int numeric_limits_impl64<b>::radix;
2267+
template <bool b> constexpr int numeric_limits_impl64<b>::min_exponent;
2268+
template <bool b> constexpr int numeric_limits_impl64<b>::min_exponent10;
2269+
template <bool b> constexpr int numeric_limits_impl64<b>::max_exponent;
2270+
template <bool b> constexpr int numeric_limits_impl64<b>::max_exponent10;
2271+
template <bool b> constexpr bool numeric_limits_impl64<b>::traps;
2272+
template <bool b> constexpr bool numeric_limits_impl64<b>::tinyness_before;
2273+
2274+
#endif // !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
2275+
2276+
} // namespace detail
2277+
2278+
} //namespace decimal
2279+
} //namespace boost
2280+
2281+
namespace std {
2282+
2283+
#ifdef __clang__
2284+
# pragma clang diagnostic push
2285+
# pragma clang diagnostic ignored "-Wmismatched-tags"
2286+
#endif
2287+
2288+
template <>
2289+
class numeric_limits<boost::decimal::decimal64_t> :
2290+
public boost::decimal::detail::numeric_limits_impl64<true> {};
2291+
2292+
#ifdef __clang__
2293+
# pragma clang diagnostic pop
2294+
#endif
2295+
22532296
} // Namespace std
22542297

22552298
#include <boost/decimal/charconv.hpp>

include/boost/decimal/decimal_fast128_t.hpp

Lines changed: 58 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1577,22 +1577,12 @@ constexpr auto quantized128f(const decimal_fast128_t& lhs, const decimal_fast128
15771577
return {lhs.full_significand(), rhs.biased_exponent(), lhs.isneg()};
15781578
}
15791579

1580-
} // namespace decimal
1581-
} // namespace boost
1582-
1583-
namespace std {
1580+
namespace detail {
15841581

1585-
template<>
1586-
#ifdef _MSC_VER
1587-
class numeric_limits<boost::decimal::decimal_fast128_t>
1588-
#else
1589-
struct numeric_limits<boost::decimal::decimal_fast128_t>
1590-
#endif
1582+
template <bool>
1583+
class numeric_limits_impl128f
15911584
{
1592-
1593-
#ifdef _MSC_VER
1594-
public:
1595-
#endif
1585+
public:
15961586

15971587
static constexpr bool is_specialized = true;
15981588
static constexpr bool is_signed = true;
@@ -1620,7 +1610,7 @@ struct numeric_limits<boost::decimal::decimal_fast128_t>
16201610
static constexpr int min_exponent10 = min_exponent;
16211611
static constexpr int max_exponent = 6144;
16221612
static constexpr int max_exponent10 = max_exponent;
1623-
static constexpr bool traps = numeric_limits<std::uint64_t>::traps;
1613+
static constexpr bool traps = std::numeric_limits<std::uint64_t>::traps;
16241614
static constexpr bool tinyness_before = true;
16251615

16261616
// Member functions
@@ -1635,6 +1625,59 @@ struct numeric_limits<boost::decimal::decimal_fast128_t>
16351625
static constexpr auto denorm_min () -> boost::decimal::decimal_fast128_t { return min(); }
16361626
};
16371627

1628+
#if !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
1629+
1630+
template <bool b> constexpr bool numeric_limits_impl128f<b>::is_specialized;
1631+
template <bool b> constexpr bool numeric_limits_impl128f<b>::is_signed;
1632+
template <bool b> constexpr bool numeric_limits_impl128f<b>::is_integer;
1633+
template <bool b> constexpr bool numeric_limits_impl128f<b>::is_exact;
1634+
template <bool b> constexpr bool numeric_limits_impl128f<b>::has_infinity;
1635+
template <bool b> constexpr bool numeric_limits_impl128f<b>::has_quiet_NaN;
1636+
template <bool b> constexpr bool numeric_limits_impl128f<b>::has_signaling_NaN;
1637+
1638+
// These members were deprecated in C++23
1639+
#if ((!defined(_MSC_VER) && (__cplusplus <= 202002L)) || (defined(_MSC_VER) && (_MSVC_LANG <= 202002L)))
1640+
template <bool b> constexpr std::float_denorm_style numeric_limits_impl128f<b>::has_denorm;
1641+
template <bool b> constexpr bool numeric_limits_impl128f<b>::has_denorm_loss;
1642+
#endif
1643+
1644+
template <bool b> constexpr std::float_round_style numeric_limits_impl128f<b>::round_style;
1645+
template <bool b> constexpr bool numeric_limits_impl128f<b>::is_iec559;
1646+
template <bool b> constexpr bool numeric_limits_impl128f<b>::is_bounded;
1647+
template <bool b> constexpr bool numeric_limits_impl128f<b>::is_modulo;
1648+
template <bool b> constexpr int numeric_limits_impl128f<b>::digits;
1649+
template <bool b> constexpr int numeric_limits_impl128f<b>::digits10;
1650+
template <bool b> constexpr int numeric_limits_impl128f<b>::max_digits10;
1651+
template <bool b> constexpr int numeric_limits_impl128f<b>::radix;
1652+
template <bool b> constexpr int numeric_limits_impl128f<b>::min_exponent;
1653+
template <bool b> constexpr int numeric_limits_impl128f<b>::min_exponent10;
1654+
template <bool b> constexpr int numeric_limits_impl128f<b>::max_exponent;
1655+
template <bool b> constexpr int numeric_limits_impl128f<b>::max_exponent10;
1656+
template <bool b> constexpr bool numeric_limits_impl128f<b>::traps;
1657+
template <bool b> constexpr bool numeric_limits_impl128f<b>::tinyness_before;
1658+
1659+
#endif // !defined(__cpp_inline_variables) || __cpp_inline_variables < 201606L
1660+
1661+
} // namespace detail
1662+
1663+
} // namespace decimal
1664+
} // namespace boost
1665+
1666+
namespace std {
1667+
1668+
#ifdef __clang__
1669+
# pragma clang diagnostic push
1670+
# pragma clang diagnostic ignored "-Wmismatched-tags"
1671+
#endif
1672+
1673+
template <>
1674+
class numeric_limits<boost::decimal::decimal_fast128_t> :
1675+
public boost::decimal::detail::numeric_limits_impl128f<true> {};
1676+
1677+
#ifdef __clang__
1678+
# pragma clang diagnostic pop
1679+
#endif
1680+
16381681
} // namespace std
16391682

16401683
#include <boost/decimal/charconv.hpp>

0 commit comments

Comments
 (0)