Fix subtle bug in fractional_width

This commit is contained in:
Howard Hinnant 2020-09-05 16:33:44 -04:00
parent 313189b0a8
commit 5e18488899
2 changed files with 22 additions and 20 deletions

View File

@ -3685,11 +3685,12 @@ struct undocumented {explicit undocumented() = default;};
// Example: width<4>::value == 2
// Example: width<10>::value == 1
// Example: width<1000>::value == 3
template <std::uint64_t n, std::uint64_t d = 10, unsigned w = 0,
bool should_continue = !(n < 2) && d != 0 && (w < 19)>
template <std::uint64_t n, std::uint64_t d, unsigned w = 0,
bool should_continue = n%d != 0 && w < 19>
struct width
{
static CONSTDATA unsigned value = 1 + width<n, d%n*10, w+1>::value;
static_assert(d > 0, "width called with zero denominator");
static CONSTDATA unsigned value = 1 + width<n%d*10, d, w+1>::value;
};
template <std::uint64_t n, std::uint64_t d, unsigned w>
@ -3718,9 +3719,10 @@ class decimal_format_seconds
{
using CT = typename std::common_type<Duration, std::chrono::seconds>::type;
using rep = typename CT::rep;
static unsigned CONSTDATA trial_width =
detail::width<CT::period::num, CT::period::den>::value;
public:
static unsigned CONSTDATA width = detail::width<CT::period::den>::value < 19 ?
detail::width<CT::period::den>::value : 6u;
static unsigned CONSTDATA width = trial_width < 19 ? trial_width : 6u;
using precision = std::chrono::duration<rep,
std::ratio<1, static_pow10<width>::value>>;

View File

@ -46,19 +46,19 @@ int
main()
{
using namespace date::detail;
static_assert(width<0>::value == 0, "");
static_assert(width<1>::value == 0, "");
static_assert(width<2>::value == 1, "");
static_assert(width<3>::value == 19, "");
static_assert(width<4>::value == 2, "");
static_assert(width<5>::value == 1, "");
static_assert(width<6>::value == 19, "");
static_assert(width<7>::value == 19, "");
static_assert(width<8>::value == 3, "");
static_assert(width<9>::value == 19, "");
static_assert(width<10>::value == 1, "");
static_assert(width<100>::value == 2, "");
static_assert(width<1000>::value == 3, "");
static_assert(width<10000>::value == 4, "");
static_assert(width<625>::value == 4, "");
static_assert(width<0, 1>::value == 0, "");
static_assert(width<1, 1>::value == 0, "");
static_assert(width<1, 2>::value == 1, "");
static_assert(width<1, 3>::value == 19, "");
static_assert(width<1, 4>::value == 2, "");
static_assert(width<1, 5>::value == 1, "");
static_assert(width<1, 6>::value == 19, "");
static_assert(width<1, 7>::value == 19, "");
static_assert(width<1, 8>::value == 3, "");
static_assert(width<1, 9>::value == 19, "");
static_assert(width<1, 10>::value == 1, "");
static_assert(width<1, 100>::value == 2, "");
static_assert(width<1, 1000>::value == 3, "");
static_assert(width<1, 10000>::value == 4, "");
static_assert(width<756, 625>::value == 4, "");
}