AsmGrader 0.0.0
Loading...
Searching...
No Matches
aggregate.hpp
Go to the documentation of this file.
1#pragma once
2
8
9#include <boost/describe/enumerators.hpp>
10#include <boost/mp11/algorithm.hpp>
11#include <boost/pfr.hpp>
12#include <boost/pfr/traits.hpp>
13#include <boost/type_index.hpp>
14#include <fmt/base.h>
15#include <fmt/format.h>
16#include <fmt/ranges.h>
17#include <range/v3/algorithm/copy.hpp>
18#include <range/v3/range/concepts.hpp>
19
20#include <string_view>
21#include <tuple>
22#include <utility>
23
24namespace asmgrader::detail {
25
29template <typename Aggregate, StaticString AggregateName, auto... Fields>
31{
33
34 constexpr auto parse(fmt::format_parse_context& ctx) {
35 // parse a potential '?' spec
36 return debug_parser.parse(ctx);
37 }
38
39 constexpr auto get_fields(const Aggregate& from) const { return std::tuple{((&from)->*(Fields.second))...}; }
40
41 constexpr auto get_named_fields(const Aggregate& from) const {
42 return std::tuple{asmgrader::pair{Fields.first, ((&from)->*(Fields.second))}...};
43 }
44
45 constexpr auto normal_format(const Aggregate& from, fmt::format_context& ctx) const {
46 // Seperator between elements
47 constexpr std::string_view sep = ", ";
48
49 const std::tuple fields{get_fields(from)};
50
51 return fmt::format_to(ctx.out(), "{}", fmt::join(fields, sep));
52 }
53
54 constexpr auto debug_format(const Aggregate& from, fmt::format_context& ctx) const {
55 fmt_appender_wrapper ctx_iter{ctx.out()};
56
57 // Seperator between elements
58 constexpr std::string_view sep = ", ";
59 // Leading and trailing output
60 constexpr std::string_view leading = " {";
61 constexpr std::string_view trailing = "}";
62
63 const std::tuple fields{get_named_fields(from)};
64
65 // Transform fields to printable output`
66 auto field_writer = [&, this, first = true](const auto& pair) mutable {
67 if (!first) {
68 ranges::copy(sep, ctx_iter);
69 }
70 first = false;
71
72 fmt::format_to(ctx_iter.out, ".{} = {}", pair.first, pair.second);
73 };
74
75 fmt::format_to(ctx_iter, "{}{}", AggregateName, leading);
76
77 std::apply([&field_writer](const auto&... elems) { (field_writer(elems), ...); }, fields);
78
79 ranges::copy(trailing, ctx_iter);
80
81 return ctx_iter.out;
82 }
83
84 constexpr auto format(const Aggregate& from, fmt::format_context& ctx) const {
86 return debug_format(from, ctx);
87 }
88 // else
89 return normal_format(from, ctx);
90 }
91};
92
93} // namespace asmgrader::detail
fmt::appender is non-comformat to the std iterator specification, and thus does not work with the eno...
Definition asm_function.hpp:123
pair(T1, T2) -> pair< T1, T2 >
StaticString(const char(&input)[N]) -> StaticString< N - 1 >
Definition debug.hpp:9
constexpr auto parse(fmt::format_parse_context &ctx)
Definition debug.hpp:12
bool is_debug_format
Definition debug.hpp:10
Definition aggregate.hpp:31
constexpr auto format(const Aggregate &from, fmt::format_context &ctx) const
Definition aggregate.hpp:84
DebugFormatter debug_parser
Definition aggregate.hpp:32
constexpr auto get_fields(const Aggregate &from) const
Definition aggregate.hpp:39
constexpr auto debug_format(const Aggregate &from, fmt::format_context &ctx) const
Definition aggregate.hpp:54
constexpr auto get_named_fields(const Aggregate &from) const
Definition aggregate.hpp:41
constexpr auto parse(fmt::format_parse_context &ctx)
Definition aggregate.hpp:34
constexpr auto normal_format(const Aggregate &from, fmt::format_context &ctx) const
Definition aggregate.hpp:45
Definition pair.hpp:11
constexpr U2 second
Definition pair.hpp:34
Definition fmt_appender_adaptor.hpp:15