@@ -347,8 +347,32 @@ namespace detail
347347#elif defined(_MSC_VER)
348348#endif
349349
350+ template <typename ... Ts, typename F>
351+ constexpr void enumerate_types (F&& f)
352+ {
353+ [&f]<auto ... Is>(std::index_sequence<Is...>) {
354+ (f.template operator ()<Ts, Is>(), ...);
355+ }(std::index_sequence_for<Ts...> {});
356+ }
357+
358+ template <auto ... Xs, typename F>
359+ constexpr void for_values (F&& f)
360+ {
361+ (f.template operator ()<Xs>(), ...);
362+ }
363+
350364} // namespace detail
351365
366+ template <auto B, auto E, typename F>
367+ constexpr void template_for (F&& f)
368+ {
369+ using t = std::common_type_t <decltype (B), decltype (E)>;
370+
371+ [&f]<auto ... Xs>(std::integer_sequence<t, Xs...>) {
372+ detail::for_values<(B + Xs)...>(f);
373+ }(std::make_integer_sequence<t, E - B> {});
374+ }
375+
352376template <auto P>
353377 requires (std::is_member_pointer_v<decltype (P)>)
354378consteval std::string_view GetName ()
@@ -392,30 +416,36 @@ consteval auto GetName()
392416#endif
393417}
394418
419+ template <typename Object, typename Callable>
420+ decltype (auto ) CallOnMembers(Object const & object, Callable&& callable)
421+ {
422+ template_for<0 , Reflection::CountMembers<Object>>(
423+ [&]<auto I>() { callable (Reflection::MemberNameOf<I, Object>, std::get<I>(Reflection::ToTuple (object))); });
424+ }
425+
395426template <typename Object>
396427std::string Inspect (Object const & object)
397428{
398- return [&]<size_t ... I>(std::index_sequence<I...>) {
399- std::string str;
400- auto const onMember = [&str]<typename Name, typename Value>(Name&& name, Value&& value) {
401- auto const InspectValue = [&str]<typename T>(T&& arg) {
402- // clang-format off
403- if constexpr (std::is_convertible_v<T, std::string>
429+ std::string str;
430+ auto const onMember = [&str]<typename Name, typename Value>(Name&& name, Value&& value) {
431+ auto const InspectValue = [&str]<typename T>(T&& arg) {
432+ // clang-format off
433+ if constexpr (std::is_convertible_v<T, std::string>
404434 || std::is_convertible_v<T, std::string_view>
405435 || std::is_convertible_v<T, char const *>) // clang-format on
406- str += std::format (" \" {}\" " , arg);
407- else
408- str += std::format (" {}" , arg);
409- };
410- if (!str.empty ())
411- str += ' ' ;
412- str += name;
413- str += ' =' ;
414- InspectValue (value);
436+ str += std::format (" \" {}\" " , arg);
437+ else
438+ str += std::format (" {}" , arg);
415439 };
416- (onMember (MemberNameOf<I, Object>, std::get<I>(Reflection::ToTuple (object))), ...);
417- return str;
418- }(std::make_index_sequence<Reflection::CountMembers<Object>> {});
440+ if (!str.empty ())
441+ str += ' ' ;
442+ str += name;
443+ str += ' =' ;
444+ InspectValue (value);
445+ };
446+
447+ CallOnMembers (object, onMember);
448+ return str;
419449}
420450
421451} // namespace Reflection
0 commit comments