Skip to content

Commit c2764ac

Browse files
authored
Merge pull request llvm#38 from Yaraslaut/example_universal_formatter
Add test for universal_formatter
2 parents 38b5ea4 + 290c8ee commit c2764ac

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Copyright 2024 Bloomberg Finance L.P.
4+
//
5+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6+
// See https://llvm.org/LICENSE.txt for license information.
7+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
//
9+
//===----------------------------------------------------------------------===//
10+
11+
// UNSUPPORTED: c++03 || c++11 || c++14 || c++17 || c++20
12+
// ADDITIONAL_COMPILE_FLAGS: -freflection
13+
// ADDITIONAL_COMPILE_FLAGS: -Wno-inconsistent-missing-override
14+
15+
// <experimental/reflection>
16+
//
17+
// [reflection]
18+
//
19+
// RUN: %{build}
20+
// RUN: %{exec} %t.exe > %t.stdout
21+
22+
#include <experimental/meta>
23+
#include <format>
24+
#include <print>
25+
26+
namespace __impl {
27+
template<auto... vals>
28+
struct replicator_type {
29+
template<typename F>
30+
constexpr void operator>>(F body) const {
31+
(body.template operator()<vals>(), ...);
32+
}
33+
};
34+
35+
template<auto... vals>
36+
replicator_type<vals...> replicator = {};
37+
}
38+
39+
template<typename R>
40+
consteval auto expand(R range) {
41+
std::vector<std::meta::info> args;
42+
for (auto r : range) {
43+
args.push_back(reflect_value(r));
44+
}
45+
return substitute(^__impl::replicator, args);
46+
}
47+
48+
struct universal_formatter {
49+
constexpr auto parse(auto& ctx) { return ctx.begin(); }
50+
51+
template <typename T>
52+
auto format(T const& t, auto& ctx) const {
53+
auto out = std::format_to(ctx.out(), "{}{{", name_of(^T));
54+
55+
auto delim = [first=true, &out]() mutable {
56+
if (!first) {
57+
*out++ = ',';
58+
*out++ = ' ';
59+
}
60+
first = false;
61+
};
62+
63+
[: expand(bases_of(^T)) :] >> [&]<auto base>{
64+
delim();
65+
out = std::format_to(out, "{}", (typename [: type_of(base) :] const&)(t));
66+
};
67+
68+
[: expand(nonstatic_data_members_of(^T)) :] >> [&]<auto mem>{
69+
delim();
70+
out = std::format_to(out, ".{}={}", name_of(mem), t.[:mem:]);
71+
};
72+
73+
*out++ = '}';
74+
return out;
75+
}
76+
};
77+
78+
struct B { int m0 = 0; };
79+
struct X : B { int m1 = 1; };
80+
struct Y : B { int m2 = 2; };
81+
class Z : public X, private Y { int m3 = 3; int m4 = 4; };
82+
83+
template <> struct std::formatter<B> : universal_formatter { };
84+
template <> struct std::formatter<X> : universal_formatter { };
85+
template <> struct std::formatter<Y> : universal_formatter { };
86+
template <> struct std::formatter<Z> : universal_formatter { };
87+
88+
int main() {
89+
// RUN: grep "Z{X{B{.m0=0}, .m1=1}, Y{B{.m0=0}, .m2=2}, .m3=3, .m4=4}" %t.stdout | wc -l
90+
std::println("{}", Z());
91+
}

0 commit comments

Comments
 (0)