44#include < nlohmann/json.hpp>
55#include < simdjson.h>
66
7+ #include < concepts>
78#include < iostream>
89#include < random>
910#include < vector>
1011
12+ template <auto ... Xs, typename F> constexpr void for_values (F &&f) {
13+ (f.template operator ()<Xs>(), ...);
14+ }
15+
16+ template <auto B, auto E, typename F> constexpr void for_range (F &&f) {
17+ using t = std::common_type_t <decltype (B), decltype (E)>;
18+
19+ [&f]<auto ... Xs>(std::integer_sequence<t, Xs...>) {
20+ for_values<(B + Xs)...>(f);
21+ }(std::make_integer_sequence<t, E - B>{});
22+ }
23+
24+ template <typename T> consteval auto member_info (int n) {
25+ return nonstatic_data_members_of (^T)[n];
26+ }
27+
1128std::mt19937 rng (12345 );
1229struct Location {
1330 double lat;
@@ -175,87 +192,25 @@ std::string nlohmann_serialize(const User &user) {
175192 return user_json.dump ();
176193}
177194
178- bool compare (const User &user1, const User &user2, const std::string &json) {
179- if (user1.id != user2.id ) {
180- std::cerr << " id mismatch: " << user1.id << " != " << user2.id << " in "
181- << json << std::endl;
182- return false ;
183- }
184- if (user1.email != user2.email ) {
185- std::cerr << " email mismatch: " << user1.email << " != " << user2.email
186- << " in " << json << std::endl;
187- return false ;
188- }
189- if (user1.username != user2.username ) {
190- std::cerr << " username mismatch: " << user1.username
191- << " != " << user2.username << " in " << json << std::endl;
192- return false ;
193- }
194- if (user1.profile .name != user2.profile .name ) {
195- std::cerr << " profile.name mismatch: " << user1.profile .name
196- << " != " << user2.profile .name << " in " << json << std::endl;
197- return false ;
198- }
199- if (user1.profile .company != user2.profile .company ) {
200- std::cerr << " profile.company mismatch: " << user1.profile .company
201- << " != " << user2.profile .company << " in " << json << std::endl;
202- return false ;
203- }
204- if (user1.profile .dob != user2.profile .dob ) {
205- std::cerr << " profile.dob mismatch: " << user1.profile .dob
206- << " != " << user2.profile .dob << " in " << json << std::endl;
207- return false ;
208- }
209- if (user1.profile .address != user2.profile .address ) {
210- std::cerr << " profile.address mismatch: " << user1.profile .address
211- << " != " << user2.profile .address << " in " << json << std::endl;
212- return false ;
213- }
214- if (user1.profile .location .lat != user2.profile .location .lat ) {
215- std::cerr << " profile.location.lat mismatch: " << user1.profile .location .lat
216- << " != " << user2.profile .location .lat << " in " << json
217- << std::endl;
218- return false ;
219- }
220- if (user1.profile .location .lng != user2.profile .location .lng ) {
221- std::cerr << " profile.location.lng"
222- << " != " << user2.profile .location .lng << " in " << json
223- << std::endl;
224- return false ;
225- }
226- if (user1.profile .about != user2.profile .about ) {
227- std::cerr << " profile.about mismatch: " << user1.profile .about
228- << " != " << user2.profile .about << " in " << json << std::endl;
229- return false ;
230- }
231- if (user1.apiKey != user2.apiKey ) {
232- std::cerr << " apiKey mismatch"
233- << " != " << user2.apiKey << " in " << json << std::endl;
234- return false ;
235- }
236- if (user1.roles .size () != user2.roles .size ()) {
237- std::cerr << " roles size mismatch: " << user1.roles .size ()
238- << " != " << user2.roles .size () << " in " << json << std::endl;
239- return false ;
240- }
241- for (size_t i = 0 ; i < user1.roles .size (); i++) {
242- if (user1.roles [i] != user2.roles [i]) {
243- std::cerr << " roles[" << i << " ] mismatch: " << user1.roles [i]
244- << " != " << user2.roles [i] << " in " << json << std::endl;
245- return false ;
195+ template <typename T>
196+ bool compare (const T &user1, const T &user2, const std::string &json) {
197+ bool result = true ;
198+ for_range<0 , nonstatic_data_members_of (^T).size ()>([&]<auto i>() {
199+ constexpr auto mem = member_info<T>(i);
200+ if constexpr (std::equality_comparable<typename [:type_of (mem):]>) {
201+ if (user1.[:mem:] != user2.[:mem:]) {
202+ std::cerr << std::format (" {} mismatch: {} != {} in {}\n " , identifier_of (mem),
203+ user1.[:mem:], user2.[:mem:], json);
204+ result = false ;
205+ }
206+ } else {
207+ if (!compare (user1.[:mem:], user2.[:mem:], json)) {
208+ result = false ;
209+ }
246210 }
247- }
248- if (user1.createdAt != user2.createdAt ) {
249- std::cerr << " createdAt mismatch: " << user1.createdAt
250- << " != " << user2.createdAt << " in " << json << std::endl;
251- return false ;
252- }
253- if (user1.updatedAt != user2.updatedAt ) {
254- std::cerr << " updatedAt mismatch: " << user1.updatedAt
255- << " != " << user2.updatedAt << " in " << json << std::endl;
256- return false ;
257- }
258- return true ;
211+ });
212+
213+ return result;
259214}
260215
261216bool round_trip_nlohmann (const User &user) {
@@ -299,5 +254,6 @@ int main() {
299254 return EXIT_FAILURE;
300255 }
301256 }
257+ printf (" \n " );
302258 return EXIT_SUCCESS;
303- }
259+ }
0 commit comments