blob: 8363eaafebcc99345eb836a2b9e5eb055f527fec [file] [log] [blame]
#include <chrono>
#include <ostream>
#define WIDEN_(C, S) ::std::__format::_Widen<C>(S, L##S)
#define WIDEN(S) WIDEN_(CharT, S)
template<typename Ret = void, typename Under = long>
struct Rep
{
using Return
= std::conditional_t<std::is_void_v<Ret>, Rep, Ret>;
Rep(Under v = 0) : val(v) {}
template<typename ORet, typename OUnder>
Rep(Rep<ORet, OUnder> o) : val(o.val) {}
operator Under() const
{ return val; }
Return
operator+() const
{ return val; }
Rep
operator-() const
{ return -val; }
friend Rep
operator+(Rep lhs, Rep rhs)
{ return lhs.val + rhs.val; }
friend Rep
operator-(Rep lhs, Rep rhs)
{ return lhs.val - rhs.val; }
friend Rep
operator*(Rep lhs, Rep rhs)
{ return lhs.val * rhs.val; }
friend Rep
operator/(Rep lhs, Rep rhs)
{ return lhs.val / rhs.val; }
friend auto operator<=>(Rep, Rep) = default;
template<typename CharT>
friend std::basic_ostream<CharT>&
operator<<(std::basic_ostream<CharT>& os, const Rep& t)
{ return os << t.val << WIDEN("[via <<]"); }
Under val;
};
template<typename Ret, typename Under1, typename Under2>
struct std::common_type<Rep<Ret, Under1>, Rep<Ret, Under2>>
{
using type = Rep<Ret, std::common_type_t<Under1, Under2>>;
};
template<typename Ret, typename Under, typename Other>
requires std::is_integral_v<Other>
struct std::common_type<Rep<Ret, Under>, Other>
{
using type = Rep<Ret, std::common_type_t<Under, Other>>;
};
template<typename Ret, typename Under, typename Other>
requires std::is_integral_v<Other>
struct std::common_type<Other, Rep<Ret, Under>>
: std::common_type<Rep<Ret, Under>, Other>
{ };
template<typename Ret, typename Under>
struct std::numeric_limits<Rep<Ret, Under>>
: std::numeric_limits<Under>
{ };
template<typename Ret, typename Under, typename CharT>
struct std::formatter<Rep<Ret, Under>, CharT>
: std::formatter<Under, CharT>
{
template<typename Out>
typename std::basic_format_context<Out, CharT>::iterator
format(const Rep<Ret>& t, std::basic_format_context<Out, CharT>& ctx) const
{
constexpr std::basic_string_view<CharT> suffix = WIDEN("[via format]");
auto out = std::formatter<Under, CharT>::format(t.val, ctx);
return std::ranges::copy(suffix, out).out;
}
};