Fix math library std::formatters & make them use format rules derived from base scalar type

This commit is contained in:
Nikita Lisitsa 2025-10-18 15:27:39 +03:00
parent b1ea7bc763
commit 78e9731d8d
5 changed files with 47 additions and 52 deletions

View file

@ -355,27 +355,19 @@ namespace std
template <typename T, std::size_t N, typename Char>
struct formatter<::psemek::math::box<T, N>, Char>
: formatter<::psemek::math::interval<T>>
{
constexpr auto parse(std::format_parse_context & ctx)
{
return ctx.begin();
}
using formatter<::psemek::math::interval<T>>::parse;
auto format(::psemek::math::point<T, N> const & p, std::format_context & ctx) const
template <typename FormatContext>
auto format(::psemek::math::box<T, N> const & b, FormatContext & ctx) const
{
if constexpr (N == 0)
for (std::size_t i = 0; i < b.dimension(); ++i)
{
return std::format_to(ctx.out(), "()");
}
else
{
auto out = ctx.out();
out = std::format_to(out, "({}", p[0]);
for (std::size_t i = 1; i < p.dimension(); ++i)
out = std::format_to(out, ", {}", p[i]);
out = std::format_to(out, ")");
return out;
if (i > 0) ctx.advance_to(std::format_to(ctx.out(), "x"));
formatter<::psemek::math::interval<T>>::format(b[i], ctx);
}
return ctx.out();
}
};

View file

@ -341,15 +341,18 @@ namespace std
template <typename T, typename Char>
struct formatter<::psemek::math::interval<T>, Char>
: formatter<T>
{
constexpr auto parse(std::format_parse_context & ctx)
{
return ctx.begin();
}
using formatter<T>::parse;
auto format(::psemek::math::interval<T> const & i, std::format_context & ctx) const
template <typename FormatContext>
auto format(::psemek::math::interval<T> const & i, FormatContext & ctx) const
{
return std::format_to(ctx.out(), "[{} .. {}]", i.min, i.max);
ctx.advance_to(std::format_to(ctx.out(), "["));
ctx.advance_to(formatter<T>::format(i.min, ctx));
ctx.advance_to(std::format_to(ctx.out(), " .. "));
ctx.advance_to(formatter<T>::format(i.max, ctx));
return std::format_to(ctx.out(), "]");
}
};

View file

@ -223,25 +223,24 @@ namespace std
template <typename T, std::size_t N>
struct hash<::psemek::math::point<T, N>>
{
std::uint64_t operator()(::psemek::math::point<T, N> const & v) const noexcept
std::uint64_t operator()(::psemek::math::point<T, N> const & p) const noexcept
{
hash<T> h;
std::uint64_t r = 0;
for (std::size_t i = 0; i < N; ++i)
::psemek::util::hash_combine(r, h(v[i]));
::psemek::util::hash_combine(r, h(p[i]));
return r;
}
};
template <typename T, std::size_t N, typename Char>
struct formatter<::psemek::math::point<T, N>, Char>
: formatter<T>
{
constexpr auto parse(std::format_parse_context & ctx)
{
return ctx.begin();
}
using formatter<T>::parse;
auto format(::psemek::math::point<T, N> const & p, std::format_context & ctx) const
template <typename FormatContext>
auto format(::psemek::math::point<T, N> const & p, FormatContext & ctx) const
{
if constexpr (N == 0)
{
@ -249,12 +248,13 @@ namespace std
}
else
{
auto out = ctx.out();
out = std::format_to(out, "({}", p[0]);
for (std::size_t i = 1; i < p.dimension(); ++i)
out = std::format_to(out, ", {}", p[i]);
out = std::format_to(out, ")");
return out;
ctx.advance_to(std::format_to(ctx.out(), "("));
for (std::size_t i = 0; i < p.dimension(); ++i)
{
if (i > 0) ctx.advance_to(std::format_to(ctx.out(), ", "));
formatter<T>::format(p[i], ctx);
}
return std::format_to(ctx.out(), ")");
}
}
};

View file

@ -346,15 +346,15 @@ namespace std
template <typename T, typename Char>
struct formatter<::psemek::math::quaternion<T>, Char>
: formatter<::psemek::math::vector<T, 4>>
{
constexpr auto parse(std::format_parse_context & ctx)
{
return ctx.begin();
}
using formatter<::psemek::math::vector<T, 4>>::parse;
auto format(::psemek::math::quaternion<T> const & q, std::format_context & ctx) const
template <typename FormatContext>
auto format(::psemek::math::quaternion<T> const & q, FormatContext & ctx) const
{
return std::format_to(ctx.out(), "{}", q.coords);
formatter<::psemek::math::vector<T, 4>>::format(q.coords, ctx);
return ctx.out();
}
};

View file

@ -524,13 +524,12 @@ namespace std
template <typename T, std::size_t N, typename Char>
struct formatter<::psemek::math::vector<T, N>, Char>
: formatter<T>
{
constexpr auto parse(std::format_parse_context & ctx)
{
return ctx.begin();
}
using formatter<T>::parse;
auto format(::psemek::math::vector<T, N> const & v, std::format_context & ctx) const
template <typename FormatContext>
auto format(::psemek::math::vector<T, N> const & v, FormatContext & ctx) const
{
if constexpr (N == 0)
{
@ -538,12 +537,13 @@ namespace std
}
else
{
auto out = ctx.out();
out = std::format_to(out, "({}", v[0]);
for (std::size_t i = 1; i < v.dimension(); ++i)
out = std::format_to(out, ", {}", v[i]);
out = std::format_to(out, ")");
return out;
ctx.advance_to(std::format_to(ctx.out(), "("));
for (std::size_t i = 0; i < v.dimension(); ++i)
{
if (i > 0) ctx.advance_to(std::format_to(ctx.out(), ", "));
formatter<T>::format(v[i], ctx);
}
return std::format_to(ctx.out(), ")");
}
}
};