Ustring format_int(T t, uint64_t flags, int prec) {
     static constexpr auto float_flags = Format::digits | Format::exp | Format::fixed | Format::general | Format::stripz;
     static constexpr auto int_flags = Format::binary | Format::decimal | Format::hex | Format::roman;
     static constexpr auto sign_flags = Format::sign | Format::signz;
     if ((flags & float_flags) && ! (flags & int_flags))
         return format_float(t, flags, prec);
     if (ibits(flags & int_flags) > 1 || ibits(flags & sign_flags) > 1)
         throw std::invalid_argument("Inconsistent integer formatting flags");
     char sign = 0;
     if (t > static_cast<T>(0)) {
         if (flags & (Format::sign | Format::signz))
             sign = '+';
     } else if (t == static_cast<T>(0)) {
         if (flags & Format::sign)
             sign = '+';
     } else {
         t = RS_Detail::SimpleAbs<T>()(t);
         sign = '-';
     }
     Ustring s;
     if (flags & Format::binary)
         s = format_radix(t, 2, prec);
     else if (flags & Format::roman)
         s = roman(unsigned(t));
     else if (flags & Format::hex)
         s = format_radix(t, 16, prec);
     else
         s = format_radix(t, 10, prec);
     if (sign)
         s.insert(s.begin(), sign);
     return s;
 }
 Ustring format_radix(T t, int base, int prec) {
     // Argument will never be negative
     Ustring s;
     auto b = static_cast<T>(base);
     prec = std::max(prec, 1);
     while (t > 0 || int(s.size()) < prec) {
         auto d = t % b;
         s += char(d + (d <= 9 ? '0' : 'a' - 10));
         t /= b;
     }
     std::reverse(s.begin(), s.end());
     return s;
 }