refl-cpp
refl.hpp
Go to the documentation of this file.
1 // The MIT License (MIT)
2 //
3 // Copyright (c) 2020 Veselin Karaganev (@veselink1) and Contributors
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #ifndef REFL_INCLUDE_HPP
24 #define REFL_INCLUDE_HPP
25 
26 #include <stddef.h> // size_t
27 #include <cstring>
28 #include <array>
29 #include <memory>
30 #include <utility> // std::move, std::forward
31 #include <optional>
32 #include <tuple>
33 #include <type_traits>
34 #include <ostream>
35 #include <sstream>
36 #include <iomanip> // std::quoted
37 
38 #ifdef _MSC_VER
39 // Disable VS warning for "Not enough arguments for macro"
40 // (emitted when a REFL_ macro is not provided any attributes)
41 #pragma warning( disable : 4003 )
42 #endif
43 
44 #if defined(__clang__)
45  #if __has_feature(cxx_rtti)
46  #define REFL_RTTI_ENABLED
47  #endif
48 #elif defined(__GNUG__)
49  #if defined(__GXX_RTTI)
50  #define REFL_RTTI_ENABLED
51  #endif
52 #elif defined(_MSC_VER)
53  #if defined(_CPPRTTI)
54  #define REFL_RTTI_ENABLED
55  #endif
56 #endif
57 
58 /**
59  * @brief The top-level refl-cpp namespace
60  * It contains a few core refl-cpp namespaces and directly exposes core classes and functions.
61  * <ul>
62  * <li>util - utility functions (for_each, map_to_tuple, etc.)</li>
63  * <li>trait - type-traits and other operations on types (is_function_v, map_t, etc.)</li>
64  * <li>runtime - utility functions and classes that always have a runtime overhead (proxy<T>, debug_str, etc.)</li>
65  * <li>member - contains the empty classes member and function (used for tagging)</li>
66  * <li>descriptor - contains the non-specialized member types (type|field_descriptor<T, N>, and operations on them (get_property, get_display_name, etc.))</li>
67  * </ul>
68  *
69  * using util::type_list; <br>
70  * using descriptor::type_descriptor; <br>
71  * using descriptor::field_descriptor; <br>
72  * using descriptor::function_descriptor; <br>
73  * using util::const_string; <br>
74  * using util::make_const_string; <br>
75  */
76 namespace refl
77 {
78  /**
79  * @brief Contains utility types and functions for working with those types.
80  */
81  namespace util
82  {
83  /**
84  * Converts a compile-time available const char* value to a const_string<N>.
85  * The argument must be a *core constant expression* and be null-terminated.
86  *
87  * @see refl::util::const_string
88  */
89 #define REFL_MAKE_CONST_STRING(CString)
90  (::refl::util::detail::copy_from_unsized<::refl::util::detail::strlen(CString)>(CString))
91 
92  /**
93  * Represents a compile-time string. Used in refl-cpp
94  * for representing names of reflected types and members.
95  * Supports constexpr concatenation and substring,
96  * and is explicitly-convertible to const char* and std::string.
97  * REFL_MAKE_CONST_STRING can be used to create an instance from a literal string.
98  *
99  * @typeparam <N> The length of the string excluding the terminating '\0' character.
100  * @see refl::descriptor::base_member_descriptor::name
101  */
102  template <size_t N>
104  {
105  /** The largest positive value size_t can hold. */
106  static constexpr size_t npos = static_cast<size_t>(-1);
107 
108  /** The length of the string excluding the terminating '\0' character. */
109  static constexpr size_t size = N;
110 
111  /**
112  * The statically-sized character buffer used for storing the string.
113  */
114  char data[N + 1];
115 
116  /**
117  * Creates an empty const_string.
118  */
119  constexpr const_string() noexcept
120  : data{}
121  {
122  }
123 
124  /**
125  * Creates a copy of a const_string.
126  */
127  constexpr const_string(const const_string<N>& other) noexcept
128  : const_string(other, std::make_index_sequence<N>())
129  {
130  }
131 
132  /**
133  * Creates a const_string by copying the contents of data.
134  */
135  constexpr const_string(const char(&data)[N + 1]) noexcept
136  : const_string(data, std::make_index_sequence<N>())
137  {
138  }
139 
140  /**
141  * Explicitly converts to const char*.
142  */
143  explicit constexpr operator const char*() const noexcept
144  {
145  return data;
146  }
147 
148  /**
149  * Explicitly converts to std::string.
150  */
151  explicit operator std::string() const noexcept
152  {
153  return data;
154  }
155 
156  /**
157  * Returns a pointer to the contained zero-terminated string.
158  */
159  constexpr const char* c_str() const noexcept
160  {
161  return data;
162  }
163 
164  /**
165  * Returns the contained string as an std::string.
166  */
167  std::string str() const noexcept
168  {
169  return data;
170  }
171 
172  /**
173  * A constexpr version of std::string::substr.
174  */
175  template <size_t Pos, size_t Count = npos>
176  constexpr auto substr() const noexcept
177  {
178  static_assert(Pos <= N);
179  constexpr size_t NewSize = std::min(Count, N - Pos);
180 
181  char buf[NewSize + 1]{};
182  for (size_t i = 0; i < NewSize; i++) {
183  buf[i] = data[Pos + i];
184  }
185 
186  return const_string<NewSize>(buf);
187  }
188 
189  private:
190 
191  /**
192  * Creates a copy of a const_string.
193  */
194  template <size_t... Idx>
195  constexpr const_string(const const_string<N>& other, std::index_sequence<Idx...>) noexcept
196  : data{ other.data[Idx]... }
197  {
198  }
199 
200  /**
201  * Creates a const_string by copying the contents of data.
202  */
203  template <size_t... Idx>
204  constexpr const_string(const char(&data)[sizeof...(Idx) + 1], std::index_sequence<Idx...>) noexcept
205  : data{ data[Idx]... }
206  {
207  }
208 
209  };
210 
211  /**
212  * Creates an empty instance of const_string<N>
213  *
214  * @see refl::util::const_string
215  */
216  constexpr const_string<0> make_const_string() noexcept
217  {
218  return {};
219  }
220 
221  /**
222  * Creates an instance of const_string<N>
223  *
224  * @see refl::util::const_string
225  */
226  template <size_t N>
227  constexpr const_string<N - 1> make_const_string(const char(&str)[N]) noexcept
228  {
229  return str;
230  }
231 
232  /**
233  * Concatenates two const_strings together.
234  *
235  * @see refl::util::const_string
236  */
237  template <size_t N, size_t M>
238  constexpr const_string<N + M> operator+(const const_string<N>& a, const const_string<M>& b) noexcept
239  {
240  char data[N + M + 1] { };
241  for (size_t i = 0; i < N; i++)
242  data[i] = a.data[i];
243  for (size_t i = 0; i < M; i++)
244  data[N + i] = b.data[i];
245  return data;
246  }
247 
248  /**
249  * Concatenates a const_string with a C-style string.
250  *
251  * @see refl::util::const_string
252  */
253  template <size_t N, size_t M>
254  constexpr const_string<N + M - 1> operator+(const const_string<N>& a, const char(&b)[M]) noexcept
255  {
256  return a + make_const_string(b);
257  }
258 
259  /**
260  * Concatenates a C-style string with a const_string.
261  *
262  * @see refl::util::const_string
263  */
264  template <size_t N, size_t M>
265  constexpr const_string<N + M - 1> operator+(const char(&a)[N], const const_string<M>& b) noexcept
266  {
267  return make_const_string(a) + b;
268  }
269 
270  /**
271  * Compares two const_strings for equality.
272  *
273  * @see refl::util::const_string
274  */
275  template <size_t N, size_t M>
276  constexpr bool operator==(const const_string<N>& a, const const_string<M>& b) noexcept
277  {
278  if constexpr (N != M) {
279  return false;
280  }
281  else {
282  for (size_t i = 0; i < M; i++) {
283  if (a.data[i] != b.data[i]) {
284  return false;
285  }
286  }
287  return true;
288  }
289  }
290 
291  /**
292  * Compares two const_strings for equality.
293  *
294  * @see refl::util::const_string
295  */
296  template <size_t N, size_t M>
297  constexpr bool operator!=(const const_string<N>& a, const const_string<M>& b) noexcept
298  {
299  return !(a == b);
300  }
301 
302  /**
303  * Compares a const_string with a C-style string for equality.
304  *
305  * @see refl::util::const_string
306  */
307  template <size_t N, size_t M>
308  constexpr bool operator==(const const_string<N>& a, const char(&b)[M]) noexcept
309  {
310  return a == make_const_string(b);
311  }
312 
313  /**
314  * Compares a const_string with a C-style string for equality.
315  *
316  * @see refl::util::const_string
317  */
318  template <size_t N, size_t M>
319  constexpr bool operator!=(const const_string<N>& a, const char(&b)[M]) noexcept
320  {
321  return a != make_const_string(b);
322  }
323 
324  /**
325  * Compares a C-style string with a const_string for equality.
326  *
327  * @see refl::util::const_string
328  */
329  template <size_t N, size_t M>
330  constexpr bool operator==(const char(&a)[N], const const_string<M>& b) noexcept
331  {
332  return make_const_string(a) == b;
333  }
334 
335  /**
336  * Compares a C-style string with a const_string for equality.
337  *
338  * @see refl::util::const_string
339  */
340  template <size_t N, size_t M>
341  constexpr bool operator!=(const char(&a)[N], const const_string<M>& b) noexcept
342  {
343  return make_const_string(a) != b;
344  }
345 
346  template <size_t N>
347  constexpr std::ostream& operator<<(std::ostream& os, const const_string<N>& str) noexcept
348  {
349  return os << str.c_str();
350  }
351 
352  namespace detail
353  {
354  constexpr size_t strlen(const char* const str)
355  {
356  return *str ? 1 + strlen(str + 1) : 0;
357  }
358 
359  template <size_t N>
360  constexpr const_string<N> copy_from_unsized(const char* const str)
361  {
362  const_string<N> cstr;
363  for (size_t i = 0; i < N; i++) {
364  cstr.data[i] = str[i];
365  }
366  return cstr;
367  }
368  } // namespace detail
369 
370  /**
371  * Represents a compile-time list of types provided as variadic template parameters.
372  * type_list is an empty TrivialType. Instances of it can freely be created to communicate
373  * the list of represented types. type_lists support many standard operations that are
374  * implicitly available with ADL-lookup. type_list is used by refl-cpp mostly to represent
375  * the list of refl::field_descriptor, refl::function_descriptor specializations that
376  * allow the compile-time reflection of a type's members.
377  *
378  * @see refl::util::for_each
379  * @see refl::util::map_to_array
380  * @see refl::util::map_to_tuple
381  * @see refl::member_list
382  *
383  * # Examples
384  * ```
385  * for_each(type_list<int, float>(), [](auto) { ... });
386  * ```
387  */
388  template <typename... Ts>
389  struct type_list
390  {
391  /** The number of types in this type_list */
392  static constexpr intptr_t size = sizeof...(Ts);
393  };
394 
395  } // namespace util
396 
397  using util::const_string;
398  using util::make_const_string;
399  using util::type_list;
400 
401  /**
402  * The contents of the refl::detail::macro_exports namespace
403  * is implicitly available in the context of REFL_TYPE/FIELD/FUNC macros.
404  * It is used to export the refl::attr:: standard attributes.
405  */
406  namespace detail
407  {
408  namespace macro_exports
409  {
410  }
411  }
412 
413 } // namespace refl
414 
415 /**
416  * refl_impl is an internal namespace that should not be used by the users of refl-cpp.
417  */
418 namespace refl_impl
419 {
420  /**
421  * Contains the generated metadata types.
422  * (i.e. type_info__)
423  */
424  namespace metadata
425  {
426  // Import everyting from macro_exports here to make it visible in REFL_ macro context.
427  using namespace refl::detail::macro_exports;
428 
429  /**
430  * The core reflection metadata type.
431  * type_info__ holds data for a type T.
432  *
433  * The non-specialized type_info__ type has a member typedef invalid_marker
434  * that can be used to detect it.
435  *
436  * Specializations of this type should provide all members of this
437  * generic definition, except invalid_marker.
438  *
439  * @typeparam <T> The reflected type.
440  */
441  template <typename T>
442  struct type_info__
443  {
444  /** Used for detecting this non-specialized type_info__ instance. */
445  struct invalid_marker{};
446 
447  /**
448  * This is a placeholder definition of which no type instances should be created.
449  */
450  template <size_t, typename>
451  struct member;
452 
453  /** The number of reflected members of the target type T. */
454  static constexpr size_t member_count{ 0 };
455 
456  /** This is a placeholder definition which shold not be referenced by well-formed programs. */
457  static constexpr refl::const_string<0> name{ "" };
458 
459  /** This is a placeholder definition which shold not be referenced by well-formed programs. */
460  static constexpr std::tuple<> attributes{ };
461  };
462 
463  /**
464  * Specializes type_info__ so that a type's const-qualification is effectively discarded.
465  */
466  template <typename T>
467  struct type_info__<const T> : public type_info__<T> {};
468 
469  /**
470  * Specializes type_info__ so that a type's volatile-qualification is effectively discarded.
471  */
472  template <typename T>
473  struct type_info__<volatile T> : public type_info__<T> {};
474 
475  /**
476  * Specializes type_info__ so that a type's const-volatile-qualification is effectively discarded.
477  */
478  template <typename T>
479  struct type_info__<const volatile T> : public type_info__<T> {};
480 
481  } // namespace metadata
482 
483 } // namespace refl_impl
484 
485 namespace refl {
486 
487  /**
488  * @brief Contains tag types denoting the different types of reflectable members.
489  *
490  * This namespace contains a number of empty types that correspond to
491  * the different member types that refl-cpp supports reflection over.
492  */
493  namespace member
494  {
495  /**
496  * An empty type which is equivalent to refl::member_descriptor_base::member_type
497  * when the reflected member is a field.
498  *
499  * @see refl::descriptor::field_descriptor
500  */
501  struct field {};
502 
503  /**
504  * An empty type which is equivalent to refl::member_descriptor_base::member_type
505  * when the reflected member is a function.
506  *
507  * @see refl::descriptor::function_descriptor
508  */
509  struct function {};
510  }
511 
512  /**
513  * @brief Provides type-level operations for refl-cpp related use-cases.
514  *
515  * The refl::trait namespace provides type-level operations useful
516  * for compile-time metaprogramming.
517  */
518  namespace trait
519  {/**
520  * Removes all reference and cv-qualifiers from T.
521  * Equivalent to std::remove_cvref which is not currently
522  * available on all C++17 compilers.
523  */
524  template <typename T>
526  {
527  typedef std::remove_cv_t<std::remove_reference_t<T>> type;
528  };
529 
530  /**
531  * Removes all reference and cv-qualifiers from T.
532  * Equivalent to std::remove_cvref_t which is not currently
533  * available on all C++17 compilers.
534  */
535  template <typename T>
536  using remove_qualifiers_t = typename remove_qualifiers<T>::type;
537 
538  namespace detail
539  {
540  /** SFIANE support for detecting whether there is a type_info__ specialization for T. */
541  template <typename T>
542  decltype(typename refl_impl::metadata::type_info__<T>::invalid_marker{}, std::false_type{}) is_reflectable_test(int);
543 
544  /** SFIANE support for detecting whether there is a type_info__ specialization for T. */
545  template <typename T>
546  std::true_type is_reflectable_test(...);
547  } // namespace detail
548 
549  /**
550  * Checks whether there is reflection metadata for the type T.
551  * Inherits from std::bool_constant<>
552  *
553  * @see REFL_TYPE
554  * @see REFL_AUTO
555  */
556  template <typename T>
557  struct is_reflectable : decltype(detail::is_reflectable_test<T>(0))
558  {
559  };
560 
561  /**
562  * Checks whether there is reflection metadata for the type T.
563  * Inherits from std::bool_constant<>
564  *
565  * @see refl::trait::is_reflectable
566  */
567  template <typename T>
568  [[maybe_unused]] static constexpr bool is_reflectable_v{ is_reflectable<T>::value };
569 
570  namespace detail
571  {
572  /** SFIANE support for detecting whether the type T supports member .begin() and .end() operations. */
573  template <typename U>
574  [[maybe_unused]] static auto is_container_test(int) -> decltype(std::declval<U>().begin(), std::declval<U>().end(), std::true_type{});
575 
576  /** SFIANE support for detecting whether the type T supports member .begin() and .end() operations. */
577  template <typename U>
578  [[maybe_unused]] static std::false_type is_container_test(...);
579  }
580 
581  /**
582  * Checks whether objects of the type T support member .begin() and .end() operations.
583  */
584  template <typename T>
585  struct is_container : decltype(detail::is_container_test<T>(0))
586  {
587  };
588 
589  /**
590  * Checks whether objects of the type T support member .begin() and .end() operations.
591  */
592  template <typename T>
593  [[maybe_unused]] static constexpr bool is_container_v{ is_container<T>::value };
594 
595  namespace detail
596  {
597  template <size_t N, typename... Ts>
598  struct get;
599 
600  template <size_t N>
601  struct get<N>
602  {
603  static_assert(N > 0, "Missing arguments list for get<N, Ts...>!");
604  };
605 
606  template <size_t N, typename T, typename... Ts>
607  struct get<N, T, Ts...> : public get<N - 1, Ts...>
608  {
609  };
610 
611  template <typename T, typename... Ts>
612  struct get<0, T, Ts...>
613  {
614  typedef T type;
615  };
616 
617  template <size_t N, typename T>
618  struct skip;
619 
620  template <size_t N, typename T, typename... Ts>
621  struct skip<N, type_list<T, Ts...>> : skip<N - 1, type_list<Ts...>>
622  {
623  };
624 
625  template <typename T, typename... Ts>
626  struct skip<0, type_list<T, Ts...>>
627  {
628  typedef type_list<T, Ts...> type;
629  };
630 
631  template <>
632  struct skip<0, type_list<>>
633  {
634  typedef type_list<> type;
635  };
636  }
637 
638  template <size_t, typename>
639  struct get;
640 
641  /**
642  * Provides a member typedef named type which is eqiuvalent to the
643  * N-th type of the provided type_list.
644  */
645  template <size_t N, typename... Ts>
646  struct get<N, type_list<Ts...>> : detail::get<N, Ts...>
647  {
648  };
649 
650  /**
651  * Equivalent to the N-th type of the provided type_list.
652  * @see get
653  */
654  template <size_t N, typename TypeList>
655  using get_t = typename get<N, TypeList>::type;
656 
657  /**
658  * Skips the first N types in the provided type_list.
659  * Provides a member typedef equivalent to the resuling type_list.
660  */
661  template <size_t N, typename TypeList>
662  using skip = detail::skip<N, TypeList>;
663 
664  /**
665  * Skips the first N types in the provided type_list.
666  * @see skip
667  */
668  template <size_t N, typename TypeList>
669  using skip_t = typename skip<N, TypeList>::type;
670 
671  template <typename T>
672  struct as_type_list;
673 
674  /**
675  * Provides a member typedef which is a type_list specialization with
676  * template type parameters equivalent to the type parameters of the provided
677  * type. The provided type must be a template specialization.
678  */
679  template <template <typename...> typename T, typename... Ts>
680  struct as_type_list<T<Ts...>>
681  {
682  typedef type_list<Ts...> type;
683  };
684 
685  template <typename T>
686  struct as_type_list : as_type_list<remove_qualifiers_t<T>>
687  {
688  };
689 
690  /**
691  * A typedef for a type_list specialization with
692  * template type parameters equivalent to the type parameters of the provided
693  * type. The provided type must be a template specialization.
694  * @see as_type_list
695  */
696  template <typename T>
697  using as_type_list_t = typename as_type_list<T>::type;
698 
699  /**
700  * Accesses first type in the list.
701  */
702  template <typename TypeList>
703  using first = get<0, TypeList>;
704 
705  /**
706  * Accesses last type in the list.
707  * @see last
708  */
709  template <typename TypeList>
710  using first_t = typename first<TypeList>::type;
711 
712  /**
713  * Accesses last type in the list.
714  */
715  template <typename TypeList>
716  using last = get<TypeList::size - 1, TypeList>;
717 
718  /**
719  * Accesses last type in the list.
720  * @see last
721  */
722  template <typename TypeList>
723  using last_t = typename last<TypeList>::type;
724 
725  /**
726  * Returns all but the first element of the list.
727  */
728  template <typename TypeList>
729  using tail = skip<1, TypeList>;
730 
731  /**
732  * Returns all but the first element of the list.
733  * @see tail
734  */
735  template <typename TypeList>
736  using tail_t = typename tail<TypeList>::type;
737 
738  namespace detail
739  {
740  template <typename, size_t, typename>
741  struct take;
742 
743  template <typename... Us>
744  struct take<type_list<Us...>, 0, type_list<>>
745  {
746  using type = type_list<Us...>;
747  };
748 
749  template <typename... Us, typename T, typename... Ts>
750  struct take<type_list<Us...>, 0, type_list<T, Ts...>>
751  {
752  using type = type_list<Us...>;
753  };
754 
755  template <size_t N, typename... Us, typename T, typename... Ts>
756  struct take<type_list<Us...>, N, type_list<T, Ts...>>
757  {
758  using type = typename take<type_list<Us..., T>, N - 1, type_list<Ts...>>::type;
759  };
760  }
761 
762  /**
763  * Returns the first N elements of the list.
764  */
765  template <size_t N, typename TypeList>
766  using take = detail::take<type_list<>, N, TypeList>;
767 
768  /**
769  * Returns the first N elements of the list.
770  */
771  template <size_t N, typename TypeList>
772  using take_t = typename take<N, TypeList>::type;
773 
774  /**
775  * Returns all but the last element of the list.
776  */
777  template <typename TypeList>
778  using init = take<TypeList::size - 1, TypeList>;
779 
780  /**
781  * Returns all but the last element of the list.
782  * @see tail
783  */
784  template <typename TypeList>
785  using init_t = typename init<TypeList>::type;
786 
787  namespace detail
788  {
789  template <typename, typename>
790  struct reverse_impl;
791 
792  template <typename... Us>
793  struct reverse_impl<type_list<Us...>, type_list<>>
794  {
795  using type = type_list<Us...>;
796  };
797 
798  template <typename... Us, typename T, typename... Ts>
799  struct reverse_impl<type_list<Us...>, type_list<T, Ts...>>
800  {
801  using type = typename reverse_impl<type_list<T, Us...>, type_list<Ts...>>::type;
802  };
803 
804  } // namespace detail
805 
806  /**
807  * Reverses a list of types.
808  */
809  template <typename TypeList>
810  struct reverse : detail::reverse_impl<type_list<>, TypeList>
811  {
812  };
813 
814  /**
815  * Reverses a list of types.
816  * @see reverse
817  */
818  template <typename TypeList>
819  using reverse_t = typename reverse<TypeList>::type;
820 
821  template <typename, typename>
822  struct concat;
823 
824  /**
825  * Concatenates two lists together.
826  */
827  template <typename... Ts, typename... Us>
828  struct concat<type_list<Ts...>, type_list<Us...>>
829  {
830  using type = type_list<Ts..., Us...>;
831  };
832 
833  /**
834  * Concatenates two lists together.
835  * @see concat
836  */
837  template <typename Lhs, typename Rhs>
838  using concat_t = typename concat<Lhs, Rhs>::type;
839 
840  /**
841  * Appends a type to the list.
842  */
843  template <typename T, typename TypeList>
844  struct append : concat<TypeList, type_list<T>>
845  {
846  };
847 
848  /**
849  * Appends a type to the list.
850  * @see prepend
851  */
852  template <typename T, typename TypeList>
853  using append_t = typename append<T, TypeList>::type;
854 
855  template <typename, typename>
856  struct prepend;
857 
858  /**
859  * Prepends a type to the list.
860  */
861  template <typename T, typename TypeList>
862  struct prepend : concat<type_list<T>, TypeList>
863  {
864  };
865 
866  /**
867  * Prepends a type to the list.
868  * @see prepend
869  */
870  template <typename T, typename TypeList>
871  using prepend_t = typename prepend<T, TypeList>::type;
872 
873  namespace detail
874  {
875  template <template<typename> typename, typename>
876  struct filter_impl;
877 
878  template <template<typename> typename Predicate>
879  struct filter_impl<Predicate, type_list<>>
880  {
881  using type = type_list<>;
882  };
883 
884  template <template<typename> typename Predicate, typename Head, typename ...Tail>
885  struct filter_impl<Predicate, type_list<Head, Tail...>>
886  {
887  using type = std::conditional_t<Predicate<Head>::value,
888  typename prepend<Head, typename filter_impl<Predicate, type_list<Tail...>>::type>::type,
889  typename filter_impl<Predicate, type_list<Tail...>>::type
890  >;
891  };
892 
893  /**
894  * filters a type_list according to a Predicate (a type-trait-like template type).
895  */
896  template <template<typename> typename Predicate>
897  struct filter
898  {
899  template <typename TypeList>
900  using apply = typename detail::filter_impl<Predicate, TypeList>::type;
901  };
902 
903  template <template<typename> typename, typename>
904  struct map_impl;
905 
906  template <template<typename> typename Mapper>
907  struct map_impl<Mapper, type_list<>>
908  {
909  using type = type_list<>;
910  };
911 
912  template <template<typename> typename Mapper, typename Head, typename ...Tail>
913  struct map_impl<Mapper, type_list<Head, Tail...>>
914  {
915  using type = typename prepend<typename Mapper<Head>::type,
916  typename map_impl<Mapper, type_list<Tail...>>::type>::type;
917  };
918 
919  /**
920  * filters a type_list according to a Predicate (a type-trait-like template type).
921  */
922  template <template<typename> typename Mapper>
923  struct map
924  {
925  template <typename TypeList>
926  using apply = typename detail::map_impl<Mapper, TypeList>::type;
927  };
928  }
929 
930  template <template<typename> typename, typename>
931  struct filter;
932 
933  /**
934  * Filters a type_list according to a predicate template.
935  */
936  template <template<typename> typename Predicate, typename... Ts>
937  struct filter<Predicate, type_list<Ts...>>
938  {
939  typedef typename detail::filter<Predicate>::template apply<type_list<Ts...>> type;
940  };
941 
942  /**
943  * Filters a type_list according to a predicate template
944  * with a static boolean member named "value" (e.g. std::is_trivial)
945  * @see filter
946  */
947  template <template<typename> typename Predicate, typename TypeList>
948  using filter_t = typename filter<Predicate, TypeList>::type;
949 
950  template <template<typename> typename, typename>
951  struct map;
952 
953  /**
954  * Transforms a type_list according to a predicate template.
955  */
956  template <template<typename> typename Mapper, typename... Ts>
957  struct map<Mapper, type_list<Ts...>>
958  {
959  typedef typename detail::map<Mapper>::template apply<type_list<Ts...>> type;
960  };
961 
962  /**
963  * Transforms a type_list according to a predicate template
964  * with a typedef named "type" (e.g. std::remove_reference)
965  * @see map
966  */
967  template <template<typename> typename Mapper, typename... Ts>
968  using map_t = typename map<Mapper, Ts...>::type;
969 
970  namespace detail
971  {
972  template <typename T>
973  struct is_instance : public std::false_type {};
974 
975  template <template<typename...> typename T, typename... Args>
976  struct is_instance<T<Args...>> : public std::true_type {};
977  }
978 
979  /**
980  * Detects whether T is a template specialization.
981  * Inherits from std::bool_constant<>.
982  */
983  template <typename T>
984  struct is_instance : detail::is_instance<T>
985  {
986  };
987 
988  /**
989  * Detects whether T is a template specialization.
990  * @see is_instance
991  */
992  template <typename T>
993  [[maybe_unused]] static constexpr bool is_instance_v{ is_instance<T>::value };
994 
995  namespace detail
996  {
997  /**
998  * Checks if T == U<Args...>.
999  * If U<Args...> != T or is invalid the result is false.
1000  */
1001  template <typename T, template<typename...> typename U, typename... Args>
1002  struct is_same_template
1003  {
1004  private:
1005  template <template<typename...> typename V, typename = V<Args...>>
1006  static auto test(int) -> std::is_same<V<Args...>, T>;
1007 
1008  template <template<typename...> typename V>
1009  static std::false_type test(...);
1010  public:
1011  static constexpr bool value{decltype(test<U>(0))::value};
1012  };
1013 
1014  template <template<typename...> typename T, typename U>
1015  struct is_instance_of : public std::false_type {};
1016 
1017  template <template<typename...> typename T, template<typename...> typename U, typename... Args>
1018  struct is_instance_of<T, U<Args...>> : public is_same_template<U<Args...>, T, Args...>
1019  {
1020  };
1021  }
1022 
1023  /**
1024  * Detects whther the type U is a template specialization of T.
1025  * (e.g. is_instance_of<std::vector<>, std::vector<int>>)
1026  * Inherits from std::bool_constant<>.
1027  */
1028  template <template<typename...>typename T, typename U>
1029  struct is_instance_of : detail::is_instance_of<T, std::remove_cv_t<U>>
1030  {
1031  };
1032 
1033  /**
1034  * Detects whther the type U is a template specialization of U.
1035  * @see is_instance_of_v
1036  */
1037  template <template<typename...>typename T, typename U>
1038  [[maybe_unused]] static constexpr bool is_instance_of_v{ is_instance_of<T, U>::value };
1039 
1040  namespace detail
1041  {
1042  template <typename, typename>
1043  struct contains_impl;
1044 
1045  template <typename T, typename... Ts>
1046  struct contains_impl<T, type_list<Ts...>> : std::disjunction<std::is_same<std::remove_cv_t<Ts>, T>...>
1047  {
1048  };
1049 
1050  template <template<typename...> typename, typename>
1051  struct contains_instance_impl;
1052 
1053  template <template<typename...> typename T, typename... Ts>
1054  struct contains_instance_impl<T, type_list<Ts...>> : std::disjunction<trait::is_instance_of<T, std::remove_cv_t<Ts>>...>
1055  {
1056  };
1057 
1058  template <typename, typename>
1059  struct contains_base_impl;
1060 
1061  template <typename T, typename... Ts>
1062  struct contains_base_impl<T, type_list<Ts...>> : std::disjunction<std::is_base_of<T, std::remove_cv_t<Ts>>...>
1063  {
1064  };
1065  }
1066 
1067  /**
1068  * Checks whether T is contained in the list of types.
1069  * Inherits from std::bool_constant<>.
1070  */
1071  template <typename T, typename TypeList>
1072  struct contains : detail::contains_impl<std::remove_cv_t<T>, TypeList>
1073  {
1074  };
1075 
1076  /**
1077  * Checks whether T is contained in the list of types.
1078  * @see contains
1079  */
1080  template <typename T, typename TypeList>
1081  [[maybe_unused]] static constexpr bool contains_v = contains<T, TypeList>::value;
1082 
1083  /**
1084  * Checks whether an instance of the template T is contained in the list of types.
1085  * Inherits from std::bool_constant<>.
1086  */
1087  template <template<typename...> typename T, typename TypeList>
1088  struct contains_instance : detail::contains_instance_impl<T, TypeList>
1089  {
1090  };
1091 
1092  /**
1093  * Checks whether an instance of the template T is contained in the list of types.
1094  * @see contains_instance
1095  */
1096  template <template<typename...> typename T, typename TypeList>
1097  [[maybe_unused]] static constexpr bool contains_instance_v = contains_instance<T, TypeList>::value;
1098 
1099  /**
1100  * Checks whether a type deriving from T is contained in the list of types.
1101  * Inherits from std::bool_constant<>.
1102  */
1103  template <typename T, typename TypeList>
1104  struct contains_base : detail::contains_base_impl<std::remove_cv_t<T>, TypeList>
1105  {
1106  };
1107 
1108  /**
1109  * Checks whether a type deriving from T is contained in the list of types.
1110  * @see contains_base
1111  */
1112  template <typename T, typename TypeList>
1113  [[maybe_unused]] static constexpr bool contains_base_v = contains_base<T, TypeList>::value;
1114 
1115  } // namespace trait
1116 
1117  /**
1118  * @brief Contains the definitions of the built-in attributes
1119  *
1120  * Contains the definitions of the built-in attributes which
1121  * are implicitly available in macro context as well as the
1122  * attr::usage namespace which contains constraints
1123  * for user-provieded attributes.
1124  *
1125  * # Examples
1126  * ```
1127  * REFL_TYPE(Point, debug(custom_printer))
1128  * REFL_FIELD(x)
1129  * REFL_FIELD(y)
1130  * REFL_END
1131  * ```
1132  */
1133  namespace attr
1134  {
1135  /**
1136  * @brief Contains a number of constraints applicable to refl-cpp attributes.
1137  *
1138  * Contains base types which create compile-time constraints
1139  * that are verified by refl-cpp. These base-types must be inherited
1140  * by custom attribute types.
1141  */
1142  namespace usage
1143  {
1144  /**
1145  * Specifies that an attribute type inheriting from this type can
1146  * only be used with REFL_TYPE()
1147  */
1148  struct type {};
1149 
1150  /**
1151  * Specifies that an attribute type inheriting from this type can
1152  * only be used with REFL_FUNC()
1153  */
1154  struct function {};
1155 
1156  /**
1157  * Specifies that an attribute type inheriting from this type can
1158  * only be used with REFL_FIELD()
1159  */
1160  struct field {};
1161 
1162  /**
1163  * Specifies that an attribute type inheriting from this type can
1164  * only be used with REFL_FUNC or REFL_FIELD.
1165  */
1166  struct member : public function, public field{};
1167 
1168  /**
1169  * Specifies that an attribute type inheriting from this type can
1170  * only be used with any one of REFL_TYPE, REFL_FIELD, REFL_FUNC.
1171  */
1172  struct any : public member, public type {};
1173  }
1174  } // namespace attr
1175 
1176  namespace descriptor
1177  {
1178  /**
1179  * @brief Represents a reflected type.
1180  */
1181  template <typename T>
1182  class type_descriptor;
1183  }
1184 
1185  namespace trait
1186  {
1187  namespace detail
1188  {
1189  template <typename T>
1190  auto member_type_test(int) -> decltype(typename T::member_type{}, std::true_type{});
1191 
1192  template <typename T>
1193  std::false_type member_type_test(...);
1194  }
1195 
1196  /**
1197  * A trait for detecting whether the type 'T' is a member descriptor.
1198  */
1199  template <typename T>
1200  struct is_member : decltype(detail::member_type_test<T>(0))
1201  {
1202  };
1203 
1204  /**
1205  * A trait for detecting whether the type 'T' is a member descriptor.
1206  */
1207  template <typename T>
1208  [[maybe_unused]] static constexpr bool is_member_v{ is_member<T>::value };
1209 
1210  namespace detail
1211  {
1212  template <typename T>
1213  struct is_field_2 : std::is_base_of<typename T::member_type, member::field>
1214  {
1215  };
1216  }
1217 
1218  /**
1219  * A trait for detecting whether the type 'T' is a field descriptor.
1220  */
1221  template <typename T>
1222  struct is_field : std::conjunction<is_member<T>, detail::is_field_2<T>>
1223  {
1224  };
1225 
1226  /**
1227  * A trait for detecting whether the type 'T' is a field descriptor.
1228  */
1229  template <typename T>
1230  [[maybe_unused]] static constexpr bool is_field_v{ is_field<T>::value };
1231 
1232  namespace detail
1233  {
1234  template <typename T>
1235  struct is_function_2 : std::is_base_of<typename T::member_type, member::function>
1236  {
1237  };
1238  }
1239 
1240  /**
1241  * A trait for detecting whether the type 'T' is a function descriptor.
1242  */
1243  template <typename T>
1244  struct is_function : std::conjunction<is_member<T>, detail::is_function_2<T>>
1245  {
1246  };
1247 
1248  /**
1249  * A trait for detecting whether the type 'T' is a function descriptor.
1250  */
1251  template <typename T>
1252  [[maybe_unused]] static constexpr bool is_function_v{ is_function<T>::value };
1253 
1254  /**
1255  * Detects whether the type T is a type_descriptor.
1256  * Inherits from std::bool_constant<>.
1257  */
1258  template <typename T>
1259  struct is_type : is_instance_of<descriptor::type_descriptor, T>
1260  {
1261  };
1262 
1263  /**
1264  * Detects whether the type T is a type_descriptor.
1265  * @see is_type
1266  */
1267  template <typename T>
1268  [[maybe_unused]] constexpr bool is_type_v{ is_type<T>::value };
1269 
1270  /**
1271  * A trait for detecting whether the type 'T' is a refl-cpp descriptor.
1272  */
1273  template <typename T>
1274  struct is_descriptor : std::disjunction<is_type<T>, is_member<T>>
1275  {
1276  };
1277 
1278  /**
1279  * A trait for detecting whether the type 'T' is a refl-cpp descriptor.
1280  */
1281  template <typename T>
1282  [[maybe_unused]] static constexpr bool is_descriptor_v{ is_descriptor<T>::value };
1283 
1284  }
1285 
1286  /**
1287  * @brief Contains the basic reflection primitives
1288  * as well as functions operating on those primitives
1289  */
1290  namespace descriptor
1291  {
1292  /**
1293  * @brief The base type for member descriptors.
1294  */
1295  template <typename T, size_t N>
1297  {
1298  protected:
1299 
1300  typedef typename refl_impl::metadata::type_info__<T>::template member<N> member;
1301 
1302  public:
1303 
1304  /** An alias for the declaring type of the reflected member. */
1305  typedef T declaring_type;
1306 
1307  /** An alias specifying the member type of member. */
1308  typedef typename member::member_type member_type;
1309 
1310  /** An alias specifying the types of the attributes of the member. (Removes CV-qualifiers.) */
1311  typedef trait::as_type_list_t<std::remove_cv_t<decltype(member::attributes)>> attribute_types;
1312 
1313  /** The type_descriptor of the declaring type. */
1314  static constexpr type_descriptor<T> declarator{ };
1315 
1316  /** The name of the reflected type. */
1317  static constexpr auto name{ member::name };
1318 
1319  /** The attributes of the reflected member. */
1320  static constexpr auto attributes{ member::attributes };
1321 
1322  };
1323 
1324  namespace detail
1325  {
1326  template <typename Member>
1327  struct static_field_invoker
1328  {
1329  static constexpr auto invoke() -> decltype(*Member::pointer)
1330  {
1331  return *Member::pointer;
1332  }
1333 
1334  template <typename U, typename M = Member, std::enable_if_t<M::is_writable, int> = 0>
1335  static constexpr auto invoke(U&& value) -> decltype(*Member::pointer = std::forward<U>(value))
1336  {
1337  return *Member::pointer = std::forward<U>(value);
1338  }
1339  };
1340 
1341  template <typename Member>
1342  struct instance_field_invoker
1343  {
1344  template <typename T>
1345  static constexpr auto invoke(T&& target) -> decltype(target.*(Member::pointer))
1346  {
1347  return target.*(Member::pointer);
1348  }
1349 
1350  template <typename T, typename U, typename M = Member, std::enable_if_t<M::is_writable, int> = 0>
1351  static constexpr auto invoke(T&& target, U&& value) -> decltype(target.*(Member::pointer) = std::forward<U>(value))
1352  {
1353  return target.*(Member::pointer) = std::forward<U>(value);
1354  }
1355  };
1356 
1357  template <typename Member>
1358  static_field_invoker<Member> field_type_switch(std::true_type);
1359 
1360  template <typename Member>
1361  instance_field_invoker<Member> field_type_switch(std::false_type);
1362  } // namespace detail
1363 
1364  /**
1365  * @brief Represents a reflected field.
1366  */
1367  template <typename T, size_t N>
1369  {
1370  using typename member_descriptor_base<T, N>::member;
1371  static_assert(trait::is_field_v<member>);
1372 
1373  public:
1374 
1375  /** Type value type of the member. */
1376  typedef typename member::value_type value_type;
1377 
1378  /** Whether the field is static or not. */
1379  static constexpr bool is_static{ !std::is_member_object_pointer_v<decltype(member::pointer)> };
1380 
1381  /** Whether the field is const or not. */
1382  static constexpr bool is_writable{ !std::is_const_v<value_type> };
1383 
1384  /** A member pointer to the reflected field of the appropriate type. */
1385  static constexpr auto pointer{ member::pointer };
1386 
1387  private:
1388 
1389  using invoker = decltype(detail::field_type_switch<field_descriptor>(std::bool_constant<is_static>{}));
1390 
1391  public:
1392 
1393  /** Returns the value of the field. (for static fields). */
1394  template <decltype(nullptr) = nullptr>
1395  static constexpr decltype(auto) get() noexcept
1396  {
1397  return *member::pointer;
1398  }
1399 
1400  /** Returns the value of the field. (for instance fields). */
1401  template <typename U>
1402  static constexpr decltype(auto) get(U&& target) noexcept
1403  {
1404  return target.*(member::pointer);
1405  }
1406 
1407  /** A synonym for get(). */
1408  template <typename... Args>
1409  constexpr auto operator()(Args&&... args) const noexcept -> decltype(invoker::invoke(std::forward<Args>(args)...))
1410  {
1411  return invoker::invoke(std::forward<Args>(args)...);
1412  }
1413 
1414  };
1415 
1416  namespace detail
1417  {
1418  template <typename Member>
1419  constexpr decltype(nullptr) get_function_pointer(...)
1420  {
1421  return nullptr;
1422  }
1423 
1424  template <typename Member>
1425  constexpr auto get_function_pointer(int) -> decltype(Member::pointer())
1426  {
1427  return Member::pointer();
1428  }
1429 
1430  template <typename Member, typename Pointer>
1431  constexpr decltype(nullptr) resolve_function_pointer(...)
1432  {
1433  return nullptr;
1434  }
1435 
1436  template <typename Member, typename Pointer>
1437  constexpr auto resolve_function_pointer(int) -> decltype(Member::template resolve<Pointer>())
1438  {
1439  return Member::template resolve<Pointer>();
1440  }
1441  }
1442 
1443  /**
1444  * @brief Represents a reflected function.
1445  */
1446  template <typename T, size_t N>
1448  {
1449  using typename member_descriptor_base<T, N>::member;
1450  static_assert(trait::is_function_v<member>);
1451 
1452  public:
1453 
1454  /**
1455  * Invokes the function with the given arguments.
1456  * If the function is an instance function, a reference
1457  * to the instance is provided as first argument.
1458  */
1459  template <typename... Args>
1460  static constexpr auto invoke(Args&&... args) -> decltype(member::invoke(std::declval<Args>()...))
1461  {
1462  return member::invoke(std::forward<Args>(args)...);
1463  }
1464 
1465  /** The return type of an invocation of this member with Args... (as if by invoke(...)). */
1466  template <typename... Args>
1467  using return_type = decltype(member::invoke(std::declval<Args>()...));
1468 
1469  /** A synonym for invoke(args...). */
1470  template <typename... Args>
1471  constexpr auto operator()(Args&&... args) const -> decltype(invoke(std::declval<Args>()...))
1472  {
1473  return invoke(std::forward<Args>(args)...);
1474  }
1475 
1476  /**
1477  * Returns a pointer to a non-overloaded function.
1478  */
1479  static constexpr auto pointer{ detail::get_function_pointer<member>(0) };
1480 
1481  /**
1482  * Whether the pointer member was correctly resolved to a concrete implementation.
1483  * If this field is false, resolve() would need to be called instead.
1484  */
1485  static constexpr bool is_resolved{ !std::is_same_v<decltype(pointer), const decltype(nullptr)> };
1486 
1487  /**
1488  * Whether the pointer can be resolved as with the specified type.
1489  */
1490  template <typename Pointer>
1491  static constexpr bool can_resolve()
1492  {
1493  return !std::is_same_v<decltype(resolve<Pointer>()), decltype(nullptr)>;
1494  }
1495 
1496  /**
1497  * Resolves the function pointer as being of type Pointer.
1498  * Required when taking a pointer to an overloaded function.
1499  */
1500  template <typename Pointer>
1501  static constexpr auto resolve()
1502  {
1503  return detail::resolve_function_pointer<member, Pointer>(0);
1504  }
1505 
1506  };
1507 
1508  namespace detail
1509  {
1510  template <typename T, size_t N>
1511  using make_descriptor = std::conditional_t<refl::trait::is_field_v<typename refl_impl::metadata::type_info__<T>::template member<N>>,
1512  field_descriptor<T, N>,
1513  std::conditional_t<refl::trait::is_function_v<typename refl_impl::metadata::type_info__<T>::template member<N>>,
1514  function_descriptor<T, N>,
1515  void
1516  >>;
1517 
1518  template <typename T, size_t... Idx>
1519  type_list<make_descriptor<T, Idx>...> enumerate_members(std::index_sequence<Idx...>);
1520 
1521  } // namespace detail
1522 
1523  /** A type_list of the member descriptors of the target type T. */
1524  template <typename T>
1525  using member_list = decltype(detail::enumerate_members<T>(std::make_index_sequence<refl_impl::metadata::type_info__<T>::member_count>{}));
1526 
1527  /** Represents a reflected type. */
1528  template <typename T>
1529  class type_descriptor
1530  {
1531  private:
1532 
1533  static_assert(refl::trait::is_reflectable_v<T>, "This type does not support reflection!");
1534 
1535  typedef refl_impl::metadata::type_info__<T> type_info;
1536 
1537  public:
1538 
1539  /** The reflected type T. */
1540  typedef T type;
1541 
1542  /** A synonym for member_list<T>. */
1543  typedef member_list<T> member_types;
1544 
1545  /** An alias specifying the types of the attributes of the member. (Removes CV-qualifiers.) */
1546  typedef trait::as_type_list_t<std::remove_cv_t<decltype(type_info::attributes)>> attribute_types;
1547 
1548  /** The list of member descriptors. */
1549  static constexpr member_list<T> members{ };
1550 
1551  /** The name of the reflected type. */
1552  static constexpr const auto name{ type_info::name };
1553 
1554  /** The attributes of the reflected type. */
1555  static constexpr const auto attributes{ type_info::attributes };
1556 
1557  };
1558  }
1559 
1560  using descriptor::member_list;
1561  using descriptor::field_descriptor;
1562  using descriptor::function_descriptor;
1563  using descriptor::type_descriptor;
1564 
1565  /** Returns true if the type T is reflectable. */
1566  template <typename T>
1567  constexpr bool is_reflectable() noexcept
1568  {
1569  return trait::is_reflectable_v<T>;
1570  }
1571 
1572  /** Returns true if the non-qualified type T is reflectable.*/
1573  template <typename T>
1574  constexpr bool is_reflectable(const T&) noexcept
1575  {
1576  return trait::is_reflectable_v<T>;
1577  }
1578 
1579  /** Returns the type descriptor for the type T. */
1580  template<typename T>
1581  constexpr type_descriptor<T> reflect() noexcept
1582  {
1583  return {};
1584  }
1585 
1586  /** Returns the type descriptor for the non-qualified type T. */
1587  template<typename T>
1588  constexpr type_descriptor<T> reflect(const T&) noexcept
1589  {
1590  return {};
1591  }
1592 
1593  namespace util
1594  {
1595  /**
1596  * Ignores all parameters. Can take an optional template parameter
1597  * specifying the return type of ignore. The return object is iniailized by {}.
1598  */
1599  template <typename T = int, typename... Ts>
1600  constexpr int ignore(Ts&&...) noexcept
1601  {
1602  return {};
1603  }
1604 
1605  /**
1606  * Returns the input paratemeter as-is. Useful for expanding variadic
1607  * template lists when only one arguments is known to be present.
1608  */
1609  template <typename T>
1610  constexpr decltype(auto) identity(T&& t) noexcept
1611  {
1612  return t;
1613  }
1614 
1615  /**
1616  * Adds const to the input reference.
1617  */
1618  template <typename T>
1619  constexpr const T& make_const(const T& value) noexcept
1620  {
1621  return value;
1622  }
1623 
1624  /**
1625  * Adds const to the input reference.
1626  */
1627  template <typename T>
1628  constexpr const T& make_const(T& value) noexcept
1629  {
1630  return value;
1631  }
1632 
1633  /**
1634  * Creates an array of type 'T' from the provided tuple.
1635  * The common type T needs to be specified, in order to prevent any
1636  * errors when using the overload taking an empty std::tuple (as there is no common type then).
1637  */
1638  template <typename T, typename... Ts>
1639  constexpr std::array<T, sizeof...(Ts)> to_array(const std::tuple<Ts...>& tuple) noexcept
1640  {
1641  return std::apply([](auto&& ... args) -> std::array<T, sizeof...(Ts)> { return { std::forward<decltype(args)>(args)... }; }, tuple);
1642  }
1643 
1644  /**
1645  * Creates an empty array of type 'T.
1646  */
1647  template <typename T>
1648  constexpr std::array<T, 0> to_array(const std::tuple<>&) noexcept
1649  {
1650  return {};
1651  }
1652 
1653  namespace detail
1654  {
1655  template <typename T, size_t... Idx>
1656  constexpr auto to_tuple([[maybe_unused]] const std::array<T, sizeof...(Idx)>& array, std::index_sequence<Idx...>) noexcept
1657  {
1658  if constexpr (sizeof...(Idx) == 0) return std::tuple<>{};
1659  else return std::make_tuple(std::get<Idx>(array)...);
1660  }
1661  }
1662 
1663  /**
1664  * Creates a tuple from the provided array.
1665  */
1666  template <typename T, size_t N>
1667  constexpr auto to_tuple(const std::array<T, N>& array) noexcept
1668  {
1669  return detail::to_tuple<T>(array, std::make_index_sequence<N>{});
1670  }
1671 
1672  namespace detail
1673  {
1674  template <typename F, typename... Carry>
1675  constexpr auto eval_in_order_to_tuple(type_list<>, std::index_sequence<>, F&&, Carry&&... carry)
1676  {
1677  if constexpr (sizeof...(Carry) == 0) return std::tuple<>{};
1678  else return std::make_tuple(std::forward<Carry>(carry)...);
1679  }
1680 
1681  // This whole jazzy workaround is needed since C++ does not specify
1682  // the order in which function arguments are evaluated and this leads
1683  // to incorrect order of evaluation (noticeable when using indexes).
1684  // Otherwise we could simply do std::make_tuple(f(Ts{}, Idx)...).
1685  template <typename F, typename T, typename... Ts, size_t I, size_t... Idx, typename... Carry>
1686  constexpr auto eval_in_order_to_tuple(type_list<T, Ts...>, std::index_sequence<I, Idx...>, F&& f, Carry&&... carry)
1687  {
1688  static_assert(std::is_trivial_v<T>, "Argument is a non-trivial type!");
1689 
1690  if constexpr (std::is_invocable_v<F, T, size_t>) {
1691  return eval_in_order_to_tuple(
1692  type_list<Ts...>{},
1693  std::index_sequence<Idx...>{},
1694  std::forward<F>(f),
1695  std::forward<Carry>(carry)..., // carry the previous results over
1696  f(T{}, I) // pass the current result after them
1697  );
1698  }
1699  else {
1700  return eval_in_order_to_tuple(
1701  type_list<Ts...>{},
1702  std::index_sequence<Idx...>{},
1703  std::forward<F>(f),
1704  std::forward<Carry>(carry)..., // carry the previous results over
1705  f(T{}) // pass the current result after them
1706  );
1707  }
1708  }
1709  }
1710 
1711  /**
1712  * Applies function F to each type in the type_list, aggregating
1713  * the results in a tuple. F can optionally take an index of type size_t.
1714  */
1715  template <typename F, typename... Ts>
1716  constexpr auto map_to_tuple(type_list<Ts...> list, F&& f)
1717  {
1718  return detail::eval_in_order_to_tuple(list, std::make_index_sequence<sizeof...(Ts)>{}, std::forward<F>(f));
1719  }
1720 
1721  /**
1722  * Applies function F to each type in the type_list, aggregating
1723  * the results in an array. F can optionally take an index of type size_t.
1724  */
1725  template <typename T, typename F, typename... Ts>
1726  constexpr auto map_to_array(type_list<Ts...> list, F&& f)
1727  {
1728  return to_array<T>(map_to_tuple(list, std::forward<F>(f)));
1729  }
1730 
1731  /**
1732  * Applies function F to each type in the type_list.
1733  * F can optionally take an index of type size_t.
1734  */
1735  template <typename F, typename... Ts>
1736  constexpr void for_each(type_list<Ts...> list, F&& f)
1737  {
1738  map_to_tuple(list, [&](auto&&... args) -> decltype(f(std::forward<decltype(args)>(args)...), 0)
1739  {
1740  f(std::forward<decltype(args)>(args)...);
1741  return 0;
1742  });
1743  }
1744 
1745  /*
1746  * Returns the initial_value unchanged.
1747  */
1748  template <typename R, typename F, typename... Ts>
1749  constexpr R accumulate(type_list<>, F&&, R&& initial_value)
1750  {
1751  return std::forward<R>(initial_value);
1752  }
1753 
1754  /*
1755  * Applies an accumulation function F to each type in the type_list.
1756  * Note: Breaking changes introduced in v0.7.0:
1757  * Behaviour changed to imitate std::accumulate.
1758  * F can now no longer take a second index argument.
1759  */
1760  template <typename R, typename F, typename T, typename... Ts>
1761  constexpr auto accumulate(type_list<T, Ts...>, F&& f, R&& initial_value)
1762  {
1763  static_assert(std::is_trivial_v<T>, "Argument is a non-trivial type!");
1764 
1765  return accumulate(type_list<Ts...> {},
1766  std::forward<F>(f),
1767  std::forward<std::invoke_result_t<F&&, R&&, T&&>>(
1768  f(std::forward<R>(initial_value), T {})));
1769  }
1770 
1771  /**
1772  * Counts the number of times the predicate F returns true.
1773  * Note: Breaking changes introduced in v0.7.0:
1774  * F can now no longer take a second index argument.
1775  */
1776  template <typename F, typename... Ts>
1777  constexpr size_t count_if(type_list<Ts...> list, F&& f)
1778  {
1779  return accumulate<size_t>(list,
1780  [&](size_t acc, const auto& t) -> size_t { return acc + (f(t) ? 1 : 0); },
1781  0);
1782  }
1783 
1784  namespace detail
1785  {
1786  template <typename F, typename... Carry>
1787  constexpr auto filter(const F&, type_list<>, type_list<Carry...> carry)
1788  {
1789  return carry;
1790  }
1791 
1792  template <typename F, typename T, typename... Ts, typename... Carry>
1793  constexpr auto filter(F f, type_list<T, Ts...>, type_list<Carry...>)
1794  {
1795  static_assert(std::is_trivial_v<T>, "Argument is a non-trivial type!");
1796  if constexpr (f(T{})) {
1797  return filter(f, type_list<Ts...>{}, type_list<Carry..., T>{});
1798  }
1799  else {
1800  return filter(f, type_list<Ts...>{}, type_list<Carry...>{});
1801  }
1802  }
1803  }
1804 
1805  /**
1806  * Filters the list according to a *constexpr* predicate.
1807  * Calling f(Ts{})... should be valid in a constexpr context.
1808  */
1809  template <typename F, typename... Ts>
1810  constexpr auto filter(type_list<Ts...> list, F&& f)
1811  {
1812  return decltype(detail::filter(std::forward<F>(f), list, type_list<>{}))();
1813  }
1814 
1815  /**
1816  * Returns the first instance that matches the *constexpr* predicate.
1817  * Calling f(Ts{})... should be valid in a constexpr context.
1818  */
1819  template <typename F, typename... Ts>
1820  constexpr auto find_first(type_list<Ts...> list, F&& f)
1821  {
1822  using result_list = decltype(detail::filter(std::forward<F>(f), list, type_list<>{}));
1823  static_assert(result_list::size != 0, "find_first did not match anything!");
1824  return trait::get_t<0, result_list>{};
1825  }
1826 
1827  /**
1828  * Returns the only instance that matches the *constexpr* predicate.
1829  * If there is no match or multiple matches, fails with static_assert.
1830  * Calling f(Ts{})... should be valid in a constexpr context.
1831  */
1832  template <typename F, typename... Ts>
1833  constexpr auto find_one(type_list<Ts...> list, F&& f)
1834  {
1835  using result_list = decltype(detail::filter(std::forward<F>(f), list, type_list<>{}));
1836  static_assert(result_list::size != 0, "find_one did not match anything!");
1837  static_assert(result_list::size == 1, "Cannot resolve multiple matches in find_one!");
1838  return trait::get_t<0, result_list>{};
1839  }
1840 
1841  /**
1842  * Returns true if any item in the list matches the predicate.
1843  * Calling f(Ts{})... should be valid in a constexpr context.
1844  */
1845  template <typename F, typename... Ts>
1846  constexpr auto contains(type_list<Ts...> list, F&& f)
1847  {
1848  using result_list = decltype(detail::filter(std::forward<F>(f), list, type_list<>{}));
1849  return result_list::size > 0;
1850  }
1851 
1852  /**
1853  * Applies a function to the elements of the type_list.
1854  */
1855  template <typename... Ts, typename F>
1856  constexpr auto apply(type_list<Ts...>, F&& f)
1857  {
1858  return f(Ts{}...);
1859  }
1860 
1861  namespace detail
1862  {
1863  template <template<typename...> typename T, ptrdiff_t N, typename... Ts>
1864  constexpr ptrdiff_t index_of_template() noexcept
1865  {
1866  if constexpr (sizeof...(Ts) <= N)
1867  {
1868  return -1;
1869  }
1870  else if constexpr (trait::is_instance_of_v<T, trait::get_t<N, type_list<Ts...>>>)
1871  {
1872  return N;
1873  }
1874  else
1875  {
1876  return index_of_template<T, N + 1, Ts...>();
1877  }
1878  }
1879 
1880  template <template<typename...> typename T, typename... Ts>
1881  constexpr ptrdiff_t index_of_template() noexcept
1882  {
1883  if (!(... || trait::is_instance_of_v<T, Ts>)) return -1;
1884  return index_of_template<T, 0, Ts...>();
1885  }
1886  }
1887 
1888  /** A synonym for std::get<N>(tuple). */
1889  template <size_t N, typename... Ts>
1890  constexpr auto& get(std::tuple<Ts...>& ts) noexcept
1891  {
1892  return std::get<N>(ts);
1893  }
1894 
1895  /** A synonym for std::get<N>(tuple). */
1896  template <size_t N, typename... Ts>
1897  constexpr const auto& get(const std::tuple<Ts...>& ts) noexcept
1898  {
1899  return std::get<N>(ts);
1900  }
1901 
1902  /** A synonym for std::get<T>(tuple). */
1903  template <typename T, typename... Ts>
1904  constexpr T& get(std::tuple<Ts...>& ts) noexcept
1905  {
1906  return std::get<T>(ts);
1907  }
1908 
1909  /** A synonym for std::get<T>(tuple). */
1910  template <typename T, typename... Ts>
1911  constexpr const T& get(const std::tuple<Ts...>& ts) noexcept
1912  {
1913  return std::get<T>(ts);
1914  }
1915 
1916  /** Returns the value of type U, where U is a template instance of T. */
1917  template <template<typename...> typename T, typename... Ts>
1918  constexpr auto& get_instance(std::tuple<Ts...>& ts) noexcept
1919  {
1920  static_assert((... || trait::is_instance_of_v<T, Ts>), "The tuple does not contain a type that is a template instance of T!");
1921  constexpr size_t idx = static_cast<size_t>(detail::index_of_template<T, Ts...>());
1922  return std::get<idx>(ts);
1923  }
1924 
1925  /** Returns the value of type U, where U is a template instance of T. */
1926  template <template<typename...> typename T, typename... Ts>
1927  constexpr const auto& get_instance(const std::tuple<Ts...>& ts) noexcept
1928  {
1929  static_assert((... || trait::is_instance_of_v<T, Ts>), "The tuple does not contain a type that is a template instance of T!");
1930  constexpr size_t idx = static_cast<size_t>(detail::index_of_template<T, Ts...>());
1931  return std::get<idx>(ts);
1932  }
1933 
1934  } // namespace util
1935 
1936  namespace attr
1937  {
1938  /**
1939  * Used to decorate a function that serves as a property.
1940  * Takes an optional friendly name.
1941  */
1942  struct property : public usage::function
1943  {
1944  const std::optional<const char*> friendly_name;
1945 
1946  constexpr property() noexcept
1947  : friendly_name{}
1948  {
1949  }
1950 
1951  constexpr property(const char* friendly_name) noexcept
1952  : friendly_name(friendly_name)
1953  {
1954  }
1955  };
1956 
1957  /**
1958  * Used to specify how a type should be displayed in debugging contexts.
1959  */
1960  template <typename F>
1961  struct debug : public usage::any
1962  {
1963  const F write;
1964 
1965  constexpr debug(F write)
1966  : write(write)
1967  {
1968  }
1969  };
1970 
1971  /**
1972  * Used to specify the base types of the target type.
1973  */
1974  template <typename... Ts>
1976  {
1977  /** An alias for a type_list of the base types. */
1978  typedef type_list<Ts...> list_type;
1979 
1980  /** An instance of a type_list of the base types. */
1981  static constexpr list_type list{ };
1982  };
1983 
1984  /**
1985  * Used to specify the base types of the target type.
1986  */
1987  template <typename... Ts>
1988  [[maybe_unused]] static constexpr base_types<Ts...> bases{ };
1989 
1990  } // namespace attr
1991 
1992  namespace detail
1993  {
1994  namespace macro_exports
1995  {
1996  using attr::property;
1997  using attr::debug;
1998  using attr::bases;
1999  }
2000  }
2001 
2002  namespace trait
2003  {
2004  /** Checks whether T is marked as a property. */
2005  template <typename T>
2006  struct is_property : std::bool_constant<
2007  trait::is_function_v<T> && trait::contains_v<attr::property, typename T::attribute_types>>
2008  {
2009  };
2010 
2011  /** Checks whether T is marked as a property. */
2012  template <typename T>
2013  [[maybe_unused]] static constexpr bool is_property_v{ is_property<T>::value };
2014  }
2015 
2016  namespace descriptor
2017  {
2018  /**
2019  * Checks whether T is a field descriptor.
2020  *
2021  * @see refl::descriptor::field_descriptor
2022  */
2023  template <typename T>
2024  constexpr bool is_field(const T) noexcept
2025  {
2026  return trait::is_field_v<T>;
2027  }
2028 
2029  /**
2030  * Checks whether T is a function descriptor.
2031  *
2032  * @see refl::descriptor::function_descriptor
2033  */
2034  template <typename T>
2035  constexpr bool is_function(const T) noexcept
2036  {
2037  return trait::is_function_v<T>;
2038  }
2039 
2040  /**
2041  * Checks whether T is a type descriptor.
2042  *
2043  * @see refl::descriptor::type_descriptor
2044  */
2045  template <typename T>
2046  constexpr bool is_type(const T) noexcept
2047  {
2048  return trait::is_type_v<T>;
2049  }
2050 
2051  /**
2052  * Checks whether T has an attribute of type A.
2053  */
2054  template <typename A, typename T>
2055  constexpr bool has_attribute(const T) noexcept
2056  {
2057  return trait::contains_base_v<A, typename T::attribute_types>;
2058  }
2059 
2060  /**
2061  * Checks whether T has an attribute of that is a template instance of A.
2062  */
2063  template <template<typename...> typename A, typename T>
2064  constexpr bool has_attribute(const T) noexcept
2065  {
2066  return trait::contains_instance_v<A, trait::as_type_list_t<typename T::attribute_types>>;
2067  }
2068 
2069  /**
2070  * Returns the value of the attribute A on T.
2071  */
2072  template <typename A, typename T>
2073  constexpr const A& get_attribute(const T t) noexcept
2074  {
2075  return util::get<A>(t.attributes);
2076  }
2077 
2078  /**
2079  * Returns the value of the attribute A on T.
2080  */
2081  template <template<typename...> typename A, typename T>
2082  constexpr const auto& get_attribute(const T t) noexcept
2083  {
2084  return util::get_instance<A>(t.attributes);
2085  }
2086 
2087  /**
2088  * Checks whether T is a member descriptor marked with the property attribute.
2089  *
2090  * @see refl::attr::property
2091  * @see refl::descriptor::get_property
2092  */
2093  template <typename T>
2094  constexpr bool is_property(const T t) noexcept
2095  {
2096  return has_attribute<attr::property>(t);
2097  }
2098 
2099  /**
2100  * Gets the property attribute.
2101  *
2102  * @see refl::attr::property
2103  * @see refl::descriptor::is_property
2104  */
2105  template <typename T>
2106  constexpr attr::property get_property(const T t) noexcept
2107  {
2108  return get_attribute<attr::property>(t);
2109  }
2110 
2111  namespace detail
2112  {
2113  struct placeholder
2114  {
2115  template <typename T>
2116  operator T() const;
2117  };
2118  } // namespace detail
2119 
2120  /**
2121  * Checks if T is a readable property or a field.
2122  */
2123  template <typename T>
2124  constexpr bool is_readable(const T) noexcept
2125  {
2126  if constexpr (trait::is_property_v<T>) {
2127  if constexpr (std::is_invocable_v<T, const typename T::declaring_type&>) {
2128  using return_type = typename T::template return_type<const typename T::declaring_type&>;
2129  return !std::is_void_v<return_type>;
2130  }
2131  else {
2132  return false;
2133  }
2134  }
2135  else {
2136  return trait::is_field_v<T>;
2137  }
2138  }
2139 
2140  /**
2141  * Checks if T is a writable property or a non-const field.
2142  */
2143  template <typename T>
2144  constexpr bool is_writable(const T) noexcept
2145  {
2146  if constexpr (trait::is_property_v<T>) {
2147  return std::is_invocable_v<T, typename T::declaring_type&, detail::placeholder>;
2148  }
2149  else if constexpr (trait::is_field_v<T>) {
2150  return !std::is_const_v<typename trait::remove_qualifiers_t<T>::value_type>;
2151  }
2152  else {
2153  return false;
2154  }
2155  }
2156 
2157  namespace detail
2158  {
2159  template <typename T>
2160  struct get_type_descriptor
2161  {
2162  typedef type_descriptor<T> type;
2163  };
2164  } // namespace detail
2165 
2166  /**
2167  * Checks if a type has a bases attribute.
2168  *
2169  * @see refl::attr::bases
2170  * @see refl::descriptor::get_bases
2171  */
2172  template <typename T>
2173  constexpr auto has_bases(const T t) noexcept
2174  {
2175  return has_attribute<attr::base_types>(t);
2176  }
2177 
2178  /**
2179  * Returns a list of the type_descriptor<T>s of the base types of the target,
2180  * as specified by the bases<A, B, ...> attribute.
2181  *
2182  * @see refl::attr::bases
2183  * @see refl::descriptor::has_bases
2184  */
2185  template <typename T>
2186  constexpr auto get_bases(const T t) noexcept
2187  {
2188  static_assert(has_bases(t), "Target type does not have a bases<A, B, ...> attribute.");
2189 
2190  constexpr auto bases = get_attribute<attr::base_types>(t);
2191  using base_types = typename decltype(bases)::list_type;
2192  return trait::map_t<detail::get_type_descriptor, base_types>{};
2193  }
2194 
2195  /**
2196  * Returns the debug name of T. (In the form of 'declaring_type::member_name').
2197  */
2198  template <typename T>
2199  const char* get_debug_name(const T& t)
2200  {
2201  static const std::string name(std::string(t.declarator.name) + "::" + t.name.str());
2202  return name.c_str();
2203  }
2204 
2205  namespace detail
2206  {
2207  constexpr bool is_upper(char ch)
2208  {
2209  return ch >= 'A' && ch <= 'Z';
2210  }
2211 
2212  constexpr char to_upper(char ch)
2213  {
2214  return ch >= 'a' && ch <= 'z'
2215  ? char(ch + ('A' - 'a'))
2216  : ch;
2217  }
2218 
2219  constexpr char to_lower(char ch)
2220  {
2221  return ch >= 'A' && ch <= 'Z'
2222  ? char(ch + ('a' - 'A'))
2223  : ch;
2224  }
2225 
2226  template <typename T, bool PreferUpper>
2227  constexpr auto normalize_bare_accessor_name()
2228  {
2229  constexpr auto str = T::name.template substr<3>();
2230  if constexpr (str.data[0] == '_') {
2231  return str.template substr<1>();
2232  }
2233  else if constexpr (!PreferUpper && str.data[0] >= 'A' && str.data[0] <= 'Z') {
2234  constexpr char s[2]{ to_lower(str.data[0]) , '\0' };
2235  return s + str.template substr<1>();
2236  }
2237  else if constexpr (PreferUpper) {
2238  constexpr char s[2]{ to_upper(str.data[0]) , '\0' };
2239  return s + str.template substr<1>();
2240  }
2241  else {
2242  return str;
2243  }
2244  }
2245 
2246  template <typename T>
2247  constexpr auto normalize_accessor_name(const T&)
2248  {
2249  constexpr T t{};
2250  if constexpr (t.name.size > 3) {
2251  constexpr auto prefix = t.name.template substr<0, 3>();
2252  constexpr bool cont_snake_or_camel = (t.name.size > 4 && t.name.data[3] == '_' && !is_upper(t.name.data[4])) || is_upper(t.name.data[3]);
2253  constexpr bool cont_pascal = is_upper(t.name.data[3]);
2254 
2255  if constexpr ((is_readable(T{}) && ((prefix == "Get" && cont_pascal) || (prefix == "get" && cont_snake_or_camel)))
2256  || (is_writable(T{}) && ((prefix == "Set" && cont_pascal) || (prefix == "set" && cont_snake_or_camel)))) {
2257  constexpr bool prefer_upper = is_upper(prefix.data[0]);
2258  return normalize_bare_accessor_name<T, prefer_upper>();
2259  }
2260  else {
2261  return t.name;
2262  }
2263  }
2264  else {
2265  return t.name;
2266  }
2267  }
2268 
2269  template <typename T>
2270  std::string get_display_name(const T& t) noexcept
2271  {
2272  if constexpr (trait::is_property_v<T>) {
2273  auto&& friendly_name = util::get<attr::property>(t.attributes).friendly_name;
2274  return friendly_name ? *friendly_name : detail::normalize_accessor_name(t).str();
2275  }
2276  return t.name.str();
2277  }
2278  } // namespace detail
2279 
2280  /**
2281  * Returns the display name of T.
2282  * Uses the friendly_name of the property attribute, or the normalized name if no friendly_name was provided.
2283  */
2284  template <typename T>
2285  const char* get_display_name(const T& t) noexcept
2286  {
2287  static const std::string name(detail::get_display_name(t));
2288  return name.c_str();
2289  }
2290 
2291  } // namespace descriptor
2292 
2293 #ifndef REFL_DETAIL_FORCE_EBO
2294 #ifdef _MSC_VER
2295 #define REFL_DETAIL_FORCE_EBO __declspec(empty_bases)
2296 #else
2297 #define REFL_DETAIL_FORCE_EBO
2298 #endif
2299 #endif
2300 
2301  /**
2302  * @brief Contains utilities that can have runtime-overhead (like proxy, debug, invoke)
2303  */
2304  namespace runtime
2305  {
2306  namespace detail
2307  {
2308  template <typename T>
2309  struct get_member_info;
2310 
2311  template <typename T, size_t N>
2312  struct get_member_info<refl::function_descriptor<T, N>>
2313  {
2314  using type = typename refl_impl::metadata::type_info__<T>::template member<N>;
2315  };
2316 
2317  template <typename T, size_t N>
2318  struct get_member_info<refl::field_descriptor<T, N>>
2319  {
2320  using type = typename refl_impl::metadata::type_info__<T>::template member<N>;
2321  };
2322 
2323  template <typename T, typename U>
2324  constexpr T& static_ref_cast(U& value) noexcept
2325  {
2326  return static_cast<T&>(value);
2327  }
2328 
2329  template <typename T, typename U>
2330  constexpr const T& static_ref_cast(const U& value) noexcept
2331  {
2332  return static_cast<const T&>(value);
2333  }
2334 
2335  /** Implements a proxy for a reflected function. */
2336  template <typename Derived, typename Func>
2337  struct REFL_DETAIL_FORCE_EBO function_proxy : public get_member_info<Func>::type::template remap<function_proxy<Derived, Func>>
2338  {
2339  function_proxy()
2340  {
2341  }
2342 
2343  template <typename Self, typename... Args>
2344  static constexpr decltype(auto) invoke_impl(Self&& self, Args&& ... args)
2345  {
2346  return Derived::template invoke_impl<Func>(static_ref_cast<Derived>(self), std::forward<Args>(args)...);
2347  }
2348 
2349  };
2350 
2351  template <typename, typename>
2352  struct REFL_DETAIL_FORCE_EBO function_proxies;
2353 
2354  /** Implements a proxy for all reflected functions. */
2355  template <typename Derived, typename... Members>
2356  struct REFL_DETAIL_FORCE_EBO function_proxies<Derived, type_list<Members...>> : public function_proxy<Derived, Members>...
2357  {
2358  };
2359 
2360  /** Implements a proxy for a reflected field. */
2361  template <typename Derived, typename Field>
2362  struct REFL_DETAIL_FORCE_EBO field_proxy : public get_member_info<Field>::type::template remap<field_proxy<Derived, Field>>
2363  {
2364  field_proxy()
2365  {
2366  }
2367 
2368  template <typename Self, typename... Args>
2369  static constexpr decltype(auto) invoke_impl(Self&& self, Args&& ... args)
2370  {
2371  return Derived::template invoke_impl<Field>(static_ref_cast<Derived>(self), std::forward<Args>(args)...);
2372  }
2373 
2374  };
2375 
2376 
2377  template <typename, typename>
2378  struct REFL_DETAIL_FORCE_EBO field_proxies;
2379 
2380  /** Implements a proxy for all reflected fields. */
2381  template <typename Derived, typename... Members>
2382  struct REFL_DETAIL_FORCE_EBO field_proxies<Derived, type_list<Members...>> : public field_proxy<Derived, Members>...
2383  {
2384  };
2385 
2386  template <typename T>
2387  using functions = trait::filter_t<trait::is_function, member_list<std::remove_reference_t<T>>>;
2388 
2389  template <typename T>
2390  using fields = trait::filter_t<trait::is_field, member_list<std::remove_reference_t<T>>>;
2391 
2392  } // namespace detail
2393 
2394  /**
2395  * @brief A proxy object that has a static interface identical to the reflected functions and fields of the target.
2396  *
2397  * A proxy object that has a static interface identical to the reflected functions and fields of the target.
2398  * Users should inherit from this class and specify an invoke_impl(Member member, Args&&... args) function.
2399  *
2400  * # Examples:
2401  * ```
2402  * template <typename T>
2403  * struct dummy_proxy : refl::runtime::proxy<dummy_proxy<T>, T> {
2404  * template <typename Member, typename Self, typename... Args>
2405  * static int invoke_impl(Self&& self, Args&&... args) {
2406  * std::cout << get_debug_name(Member()) << " called with " << sizeof...(Args) << " parameters!\n";
2407  * return 0;
2408  * }
2409  * };
2410  * ```
2411  */
2412  template <typename Derived, typename Target>
2414  : public detail::function_proxies<proxy<Derived, Target>, detail::functions<Target>>
2415  , public detail::field_proxies<proxy<Derived, Target>, detail::fields<Target>>
2416  {
2417  static_assert(
2418  sizeof(detail::function_proxies<proxy<Derived, Target>, detail::functions<Target>>) == 1,
2419  "Multiple inheritance EBO did not kick in! "
2420  "You could try defining the REFL_DETAIL_FORCE_EBO macro appropriately to enable it on the required types. "
2421  "Default for MSC is `__declspec(empty_bases)`.");
2422 
2423  static_assert(
2424  trait::is_reflectable_v<Target>,
2425  "Target type must be reflectable!");
2426 
2427  typedef Target target_type;
2428 
2429  constexpr proxy() noexcept {}
2430 
2431  private:
2432 
2433  template <typename P, typename F>
2434  friend struct detail::function_proxy;
2435 
2436  template <typename P, typename F>
2437  friend struct detail::field_proxy;
2438 
2439  // Called by one of the function_proxy/field_proxy bases.
2440  template <typename Member, typename Self, typename... Args>
2441  static constexpr decltype(auto) invoke_impl(Self&& self, Args&& ... args)
2442  {
2443  return Derived::template invoke_impl<Member>(detail::static_ref_cast<Derived>(self), std::forward<Args>(args)...);
2444  }
2445 
2446  };
2447 
2448  } // namespace runtime
2449 
2450  namespace trait
2451  {
2452  template <typename>
2453  struct is_proxy;
2454 
2455  template <typename T>
2456  struct is_proxy
2457  {
2458  private:
2459  template <typename Derived, typename Target>
2460  static std::true_type test(runtime::proxy<Derived, Target>*);
2461  static std::false_type test(...);
2462  public:
2463  static constexpr bool value{ !std::is_reference_v<T> && decltype(test(std::declval<remove_qualifiers_t<T>*>()))::value };
2464  };
2465 
2466  template <typename T>
2467  [[maybe_unused]] static constexpr bool is_proxy_v{ is_proxy<T>::value };
2468  }
2469 
2470  namespace runtime
2471  {
2472  template <typename T>
2473  void debug(std::ostream& os, const T& value, bool compact = false);
2474 
2475  namespace detail
2476  {
2477  template <typename T, typename = decltype(std::declval<std::ostream&>() << std::declval<T>())>
2478  std::true_type is_ostream_printable_test(int);
2479 
2480  template <typename T>
2481  std::false_type is_ostream_printable_test(...);
2482 
2483  template <typename T>
2484  constexpr bool is_ostream_printable_v{ decltype(is_ostream_printable_test<T>(0))::value };
2485 
2486  int next_depth(int depth)
2487  {
2488  return depth == -1 || depth > 8
2489  ? -1
2490  : depth + 1;
2491  }
2492 
2493  void indent(std::ostream& os, int depth)
2494  {
2495  for (int i = 0; i < depth; i++) {
2496  os << " ";
2497  }
2498  }
2499 
2500  template <typename T>
2501  void debug_impl(std::ostream& os, const T& value, [[maybe_unused]] int depth);
2502 
2503  template <typename T>
2504  void debug_detailed(std::ostream& os, const T& value, int depth)
2505  {
2506  using type_descriptor = type_descriptor<T>;
2507  bool compact = depth == -1;
2508  // print type with members enclosed in braces
2509  os << type_descriptor::name << " { ";
2510  if (!compact) os << '\n';
2511 
2512  constexpr auto readable_members = filter(type_descriptor::members, [](auto member) { return is_readable(member); });
2513  for_each(readable_members, [&](auto member, [[maybe_unused]] auto index) {
2514  int new_depth = next_depth(depth);
2515 
2516  indent(os, new_depth);
2517  os << get_display_name(member) << " = ";
2518 
2519  if constexpr (trait::contains_instance_v<attr::debug, typename decltype(member)::attribute_types>) {
2520  // use the debug attribute to print
2521  auto debug_attr = util::get_instance<attr::debug>(member.attributes);
2522  debug_attr.write(os, value);
2523  }
2524  else {
2525  debug_impl(os, member(value), new_depth);
2526  }
2527 
2528  if (!compact || index + 1 != readable_members.size) {
2529  os << ", ";
2530  }
2531  if (!compact) {
2532  indent(os, depth);
2533  os << '\n';
2534  }
2535  });
2536 
2537  if (compact) os << ' ';
2538  indent(os, depth);
2539  os << '}';
2540  }
2541 
2542  template <typename T>
2543  void debug_reflectable(std::ostream& os, const T& value, int depth)
2544  {
2545  using type_descriptor = type_descriptor<T>;
2546  if constexpr (trait::contains_instance_v<attr::debug, typename type_descriptor::attribute_types>) {
2547  // use the debug attribute to print
2548  auto debug_attr = util::get_instance<attr::debug>(type_descriptor::attributes);
2549  debug_attr.write(os, value);
2550  }
2551  else if constexpr (detail::is_ostream_printable_v<T>) {
2552  // type supports printing natively, just use that
2553  os << value;
2554  }
2555  else {
2556  debug_detailed(os, value, depth);
2557  }
2558  }
2559 
2560  template <typename T>
2561  void debug_container(std::ostream& os, const T& value, int depth)
2562  {
2563  bool compact = depth == -1;
2564  os << "[";
2565 
2566  auto end = value.end();
2567  for (auto it = value.begin(); it != end; ++it)
2568  {
2569  if (!compact) os << '\n';
2570  int new_depth = next_depth(depth);
2571  indent(os, new_depth);
2572 
2573  debug_impl(os, *it, new_depth);
2574  if (std::next(it, 1) != end) {
2575  os << ", ";
2576  }
2577  else if (!compact) {
2578  os << '\n';
2579  }
2580  }
2581 
2582  indent(os, depth);
2583  os << "]";
2584  }
2585 
2586  template <typename T>
2587  void debug_impl(std::ostream& os, const T& value, int depth)
2588  {
2589  using no_pointer_t = std::remove_pointer_t<T>;
2590 
2591  if constexpr (std::is_same_v<bool, T>) {
2592  os << (value ? "true" : "false");
2593  }
2594  else if constexpr (std::is_pointer_v<T> && !std::is_void_v<no_pointer_t> && trait::is_reflectable_v<no_pointer_t>) {
2595  if (value == nullptr) {
2596  os << "nullptr";
2597  }
2598  else {
2599  os << '&';
2600  debug_impl(os, *value, -1);
2601  }
2602  }
2603  else if constexpr (trait::is_reflectable_v<T>) {
2604  debug_reflectable(os, value, depth);
2605  }
2606  else if constexpr (detail::is_ostream_printable_v<T>) {
2607  os << value;
2608  }
2609  else if constexpr (trait::is_container_v<T>) {
2610  debug_container(os, value, depth);
2611  }
2612  else {
2613  os << "(not printable)";
2614  }
2615  }
2616  }
2617 
2618  /**
2619  * Writes the debug representation of value to the given std::ostream.
2620  * Calls the function specified by the debug<F> attribute whenever possible,
2621  * before falling back to recursively interating the members and printing them.
2622  * Takes an optional arguments specifying whether to print a compact representation.
2623  * The compact representation contains no newlines.
2624  */
2625  template <typename T>
2626  void debug(std::ostream& os, const T& value, [[maybe_unused]] bool compact)
2627  {
2628  static_assert(trait::is_reflectable_v<T> || trait::is_container_v<T> || detail::is_ostream_printable_v<T>,
2629  "Type is not reflectable, not a container of reflectable types and does not support operator<<(std::ostream&, T)!");
2630 
2631  detail::debug_impl(os, value, compact ? -1 : 0);
2632  }
2633 
2634  /**
2635  * Writes the compact debug representation of the provided values to the given std::ostream.
2636  */
2637  template <typename... Ts>
2638  void debug_all(std::ostream& os, const Ts&... values)
2639  {
2640  refl::runtime::debug(os, std::forward_as_tuple(static_cast<const Ts&>(values)...), true);
2641  }
2642 
2643  /**
2644  * Writes the debug representation of the provided value to an std::string and returns it.
2645  * Takes an optional arguments specifying whether to print a compact representation.
2646  * The compact representation contains no newlines.
2647  */
2648  template <typename T>
2649  std::string debug_str(const T& value, bool compact = false)
2650  {
2651  std::stringstream ss;
2652  debug(ss, value, compact);
2653  return ss.str();
2654  }
2655 
2656  /**
2657  * Writes the compact debug representation of the provided values to an std::string and returns it.
2658  */
2659  template <typename... Ts>
2660  std::string debug_all_str(const Ts&... values)
2661  {
2662  return refl::runtime::debug_str(std::forward_as_tuple(static_cast<const Ts&>(values)...), true);
2663  }
2664 
2665  /**
2666  * Invokes the specified member with the provided arguments.
2667  * When used with a member that is a field, the function gets or sets the value of the field.
2668  * The list of members is initially filtered by the type of the arguments provided.
2669  * THe filtered list is then searched at runtime by member name for the specified member
2670  * and that member is then invoked by operator(). If no match is found,
2671  * an std::runtime_error is thrown.
2672  */
2673  template <typename U, typename T, typename... Args>
2674  U invoke(T&& target, const char* name, Args&&... args)
2675  {
2676  using type = std::remove_reference_t<T>;
2677  static_assert(refl::trait::is_reflectable_v<type>, "Unsupported type!");
2678  typedef type_descriptor<type> type_descriptor;
2679 
2680  std::optional<U> result;
2681 
2682  bool found{ false };
2683  for_each(type_descriptor::members, [&](auto member) {
2684  using member_t = decltype(member);
2685  if (found) return;
2686 
2687  if constexpr (std::is_invocable_r_v<U, decltype(member), T, Args...>) {
2688  if constexpr (trait::is_field_v<member_t>) {
2689  if (std::strcmp(member.name.c_str(), name) == 0) {
2690  result.emplace(member(target, std::forward<Args>(args)...));
2691  found = true;
2692  }
2693  }
2694  else if constexpr (trait::is_function_v<member_t>) {
2695  if (std::strcmp(member.name.c_str(), name) == 0) {
2696  result.emplace(member(target, std::forward<Args>(args)...));
2697  found = true;
2698  }
2699  }
2700  }
2701  });
2702 
2703  if (found) {
2704  return std::move(*result);
2705  }
2706  else {
2707  throw std::runtime_error(std::string("The member ")
2708  + type_descriptor::name.str() + "::" + name
2709  + " is not compatible with the provided parameters or return type, is not reflected or does not exist!");
2710  }
2711  }
2712 
2713  } // namespace runtime
2714 
2715 } // namespace refl
2716 
2717 namespace refl::detail
2718 {
2719  constexpr bool validate_attr_unique(type_list<>) noexcept
2720  {
2721  return true;
2722  }
2723 
2724  /** Statically asserts that all types in Ts... are unique. */
2725  template <typename T, typename... Ts>
2726  constexpr bool validate_attr_unique(type_list<T, Ts...>) noexcept
2727  {
2728  constexpr bool cond = (... && (!std::is_same_v<T, Ts> && validate_attr_unique(type_list<Ts>{})));
2729  static_assert(cond, "Some of the attributes provided have duplicate types!");
2730  return cond;
2731  }
2732 
2733  template <typename Req, typename Attr>
2734  constexpr bool validate_attr_usage() noexcept
2735  {
2736  return std::is_base_of_v<Req, Attr>;
2737  }
2738 
2739  /**
2740  * Statically asserts that all arguments inherit
2741  * from the appropriate bases to be used with Req.
2742  * Req must be one of the types defined in attr::usage.
2743  */
2744  template <typename Req, typename... Args>
2745  constexpr std::tuple<trait::remove_qualifiers_t<Args>...> make_attributes(Args&&... args) noexcept
2746  {
2747  constexpr bool check_unique = validate_attr_unique(type_list<Args...>{});
2748  static_assert(check_unique, "Some of the supplied attributes cannot be used on this declaration!");
2749 
2750  constexpr bool check_usage = (... && validate_attr_usage<Req, trait::remove_qualifiers_t<Args>>());
2751  static_assert(check_usage, "Some of the supplied attributes cannot be used on this declaration!");
2752 
2753  return std::tuple<trait::remove_qualifiers_t<Args>...>{ std::forward<Args>(args)... };
2754  }
2755 
2756  template <typename T, typename...>
2757  struct head
2758  {
2759  typedef T type;
2760  };
2761 
2762  /**
2763  * Accesses the first type T of Ts...
2764  * Used to allow for SFIANE to kick in in the implementation of REFL_FUNC.
2765  */
2766  template <typename T, typename... Ts>
2767  using head_t = typename head<T, Ts...>::type;
2768 
2769 } // namespace refl::detail
2770 
2771 /********************************/
2772 /* Metadata-generation macros */
2773 /********************************/
2774 
2775 #define REFL_DETAIL_STR_IMPL(...) #__VA_ARGS__
2776 /** Used to stringify input separated by commas (e.g. template specializations with multiple types). */
2777 #define REFL_DETAIL_STR(...) REFL_DETAIL_STR_IMPL(__VA_ARGS__)
2778 /** Used to group input containing commas (e.g. template specializations with multiple types). */
2779 #define REFL_DETAIL_GROUP(...) __VA_ARGS__
2780 
2781 /**
2782  * Expands to the appropriate attributes static member variable.
2783  * DeclType must be the name of one of the constraints defined in attr::usage.
2784  * __VA_ARGS__ is the list of attributes.
2785  */
2786 #define REFL_DETAIL_ATTRIBUTES(DeclType, ...)
2787  static constexpr auto attributes{ ::refl::detail::make_attributes<::refl::attr::usage:: DeclType>(__VA_ARGS__) };
2788 
2789 /**
2790  * Expands to the body of a type_info__ specialization.
2791  */
2792 #define REFL_DETAIL_TYPE_BODY(TypeName, ...)
2793  typedef REFL_DETAIL_GROUP TypeName type;
2794  REFL_DETAIL_ATTRIBUTES(type, __VA_ARGS__)
2795  static constexpr auto name{ ::refl::util::make_const_string(REFL_DETAIL_STR(REFL_DETAIL_GROUP TypeName)) };
2796  static constexpr size_t member_index_offset = __COUNTER__ + 1;
2797  template <size_t N, typename = void>
2798  struct member {};
2799 
2800 /**
2801  * Creates reflection information for a specified type. Takes an optional attribute list.
2802  * This macro must only be expanded in the global namespace.
2803  *
2804  * # Examples:
2805  * ```
2806  * REFL_TYPE(Point)
2807  * ...
2808  * REFL_END
2809  * ```
2810  */
2811 #define REFL_TYPE(TypeName, ...)
2812  namespace refl_impl::metadata { template<> struct type_info__<TypeName> {
2813  REFL_DETAIL_TYPE_BODY((TypeName), __VA_ARGS__)
2814 
2815 /**
2816  * Creates reflection information for a specified type template. Takes an optional attribute list.
2817  * TemplateDeclaration must be a panenthesis-enclosed list declaring the template parameters. (e.g. (typename A, typename B)).
2818  * TypeName must be the fully-specialized type name and should also be enclosed in panenthesis. (e.g. (MyType<A, B>))
2819  * This macro must only be expanded in the global namespace.
2820  *
2821  * # Examples:
2822  * ```
2823  * REFL_TEMPLATE((typename T), (std::vector<T>))
2824  * ...
2825  * REFL_END
2826  * ```
2827  */
2828 #define REFL_TEMPLATE(TemplateDeclaration, TypeName, ...)
2829  namespace refl_impl::metadata { template <REFL_DETAIL_GROUP TemplateDeclaration> struct type_info__<REFL_DETAIL_GROUP TypeName> {
2830  REFL_DETAIL_TYPE_BODY(TypeName, __VA_ARGS__)
2831 
2832 /**
2833  * Terminated the declaration of reflection metadata for a particular type.
2834  *
2835  * # Examples:
2836  * ```
2837  * REFL_TYPE(Point)
2838  * ...
2839  * REFL_END
2840  */
2841 #define REFL_END
2842  static constexpr size_t member_count{ __COUNTER__ - member_index_offset };
2843  }; }
2844 
2845 #define REFL_DETAIL_MEMBER_HEADER template<typename Unused__> struct member<__COUNTER__ - member_index_offset, Unused__>
2846 
2847 #define REFL_DETAIL_MEMBER_COMMON(MemberType_, MemberName_, ...)
2848  typedef ::refl::member::MemberType_ member_type;
2849  static constexpr auto name{ ::refl::util::make_const_string(REFL_DETAIL_STR(MemberName_)) };
2850  REFL_DETAIL_ATTRIBUTES(MemberType_, __VA_ARGS__)
2851 
2852 /** Creates the support infrastructure needed for the refl::runtime::proxy type. */
2853 /*
2854  There can be a total of 12 differently qualified member functions with the same name.
2855  Providing remaps for non-const and const-only strikes a balance between compilation time and usability.
2856  And even though there are many other remap implementation possibilities (like virtual, field variants),
2857  adding them was considered to not be efficient from a compilation-time point of view.
2858 */
2859 #define REFL_DETAIL_MEMBER_PROXY(MemberName_)
2860  template <typename Proxy> struct remap {
2861  template <typename... Args> decltype(auto) MemberName_(Args&&... args) {
2862  return Proxy::invoke_impl(static_cast<Proxy&>(*this), ::std::forward<Args>(args)...);
2863  }
2864  template <typename... Args> decltype(auto) MemberName_(Args&&... args) const {
2865  return Proxy::invoke_impl(static_cast<const Proxy&>(*this), ::std::forward<Args>(args)...);
2866  }
2867  }
2868 
2869 /**
2870  * Creates reflection information for a public field. Takes an optional attribute list.
2871  */
2872 #define REFL_FIELD(FieldName_, ...)
2873  REFL_DETAIL_MEMBER_HEADER {
2874  REFL_DETAIL_MEMBER_COMMON(field, FieldName_, __VA_ARGS__)
2875  public:
2876  typedef decltype(type::FieldName_) value_type;
2877  static constexpr auto pointer{ &type::FieldName_ };
2878  REFL_DETAIL_MEMBER_PROXY(FieldName_);
2879  };
2880 
2881 /**
2882  * Creates reflection information for a public functions. Takes an optional attribute list.
2883  */
2884 #define REFL_FUNC(FunctionName_, ...)
2885  REFL_DETAIL_MEMBER_HEADER {
2886  REFL_DETAIL_MEMBER_COMMON(function, FunctionName_, __VA_ARGS__)
2887  public:
2888  template<typename Self, typename... Args> static constexpr auto invoke(Self&& self, Args&&... args) -> decltype(std::declval<Self>().FunctionName_(::std::declval<Args>()...)) {
2889  return ::std::forward<Self>(self).FunctionName_(::std::forward<Args>(args)...);
2890  }
2891  template<typename... Args> static constexpr auto invoke(Args&&... args) -> decltype(::refl::detail::head_t<type, Args...>::FunctionName_(::std::declval<Args>()...)) {
2892  return ::refl::detail::head_t<type, Args...>::FunctionName_(::std::forward<Args>(args)...);
2893  }
2894  template <typename Dummy = void>
2895  static constexpr auto pointer() -> decltype(&::refl::detail::head_t<type, Dummy>::FunctionName_) { return &::refl::detail::head_t<type, Dummy>::FunctionName_; }
2896  REFL_DETAIL_MEMBER_PROXY(FunctionName_);
2897  };
2898 
2899 /********************************/
2900 /* Default Reflection Metadata */
2901 /********************************/
2902 
2903 #define REFL_DETAIL_PRIMITIVE(TypeName)
2904  REFL_TYPE(TypeName)
2905  REFL_END
2906 
2907  // Char types.
2908  REFL_DETAIL_PRIMITIVE(char);
2909  REFL_DETAIL_PRIMITIVE(wchar_t);
2910  REFL_DETAIL_PRIMITIVE(char16_t);
2911  REFL_DETAIL_PRIMITIVE(char32_t);
2912 #ifdef __cpp_lib_char8_t
2913  REFL_DETAIL_PRIMITIVE(char8_t);
2914 #endif
2915 
2916  // Integral types.
2917  REFL_DETAIL_PRIMITIVE(bool);
2918  REFL_DETAIL_PRIMITIVE(signed char);
2919  REFL_DETAIL_PRIMITIVE(unsigned char);
2920  REFL_DETAIL_PRIMITIVE(signed short);
2921  REFL_DETAIL_PRIMITIVE(unsigned short);
2922  REFL_DETAIL_PRIMITIVE(signed int);
2923  REFL_DETAIL_PRIMITIVE(unsigned int);
2924  REFL_DETAIL_PRIMITIVE(signed long);
2925  REFL_DETAIL_PRIMITIVE(unsigned long);
2926  REFL_DETAIL_PRIMITIVE(signed long long);
2927  REFL_DETAIL_PRIMITIVE(unsigned long long);
2928 
2929  // Floating point types.
2930  REFL_DETAIL_PRIMITIVE(float);
2931  REFL_DETAIL_PRIMITIVE(double);
2932  REFL_DETAIL_PRIMITIVE(long double);
2933 
2934  // Other types.
2935  REFL_DETAIL_PRIMITIVE(decltype(nullptr));
2936 
2937  // Void type.
2938  REFL_TYPE(void)
2939  REFL_END
2940 
2941 #undef REFL_DETAIL_PRIMITIVE
2942 
2943 #define REFL_DETAIL_POINTER(Ptr)
2944  template<typename T>
2945  struct type_info__<T Ptr> {
2946  typedef T Ptr type;
2947  template <size_t N>
2948  struct member {};
2949  static constexpr auto name{ ::refl::util::make_const_string(#Ptr) };
2950  static constexpr ::std::tuple<> attributes{ };
2951  static constexpr size_t member_count{ 0 };
2952  }
2953 
2954  namespace refl_impl
2955  {
2956  namespace metadata
2957  {
2958  REFL_DETAIL_POINTER(*);
2959  REFL_DETAIL_POINTER(&);
2960  REFL_DETAIL_POINTER(&&);
2961  }
2962  }
2963 
2964 #undef REFL_DETAIL_POINTER
2965 
2966 namespace refl::detail
2967 {
2968  template <typename T>
2969  auto write_impl(std::ostream& os, T&& t) -> decltype((os << t), void())
2970  {
2971  os << t;
2972  }
2973 
2974  template <typename T>
2975  void write_impl(std::ostream& os, const volatile T* ptr)
2976  {
2977  auto f(os.flags());
2978  os << "(" << reflect<T>().name << "*)" << std::hex << ptr;
2979  os.flags(f);
2980  }
2981 
2982  inline void write_impl(std::ostream& os, const char* ptr)
2983  {
2984  os << ptr;
2985  }
2986 
2987  inline void write_impl(std::ostream& os, const std::exception& e)
2988  {
2989  os << "Exception";
2990 #ifdef REFL_RTTI_ENABLED
2991  os << " (" << typeid(e).name() << ")";
2992 #endif
2993  os << ": `" << e.what() << "`";
2994  }
2995 
2996  inline void write_impl(std::ostream& os, const std::string& t)
2997  {
2998  os << std::quoted(t);
2999  }
3000 
3001  inline void write_impl(std::ostream& os, const std::wstring& t)
3002  {
3003 #ifdef _MSC_VER
3004 // Disable the "wcsrtombs is unsafe" warning in VS
3005 #pragma warning(push)
3006 #pragma warning(disable:4996)
3007 #endif
3008  std::mbstate_t state = std::mbstate_t();
3009  const wchar_t* wsptr = t.c_str();
3010  std::size_t len = 1 + std::wcsrtombs(nullptr, &wsptr, 0, &state);
3011 
3012  std::string mbstr(len, '\0');
3013  std::wcsrtombs(mbstr.data(), &wsptr, mbstr.size(), &state);
3014 
3015  os << std::quoted(mbstr);
3016 #ifdef _MSC_VER
3017 #pragma warning(pop)
3018 #endif
3019  }
3020 
3021  template <typename Tuple, size_t... Idx>
3022  void write_impl(std::ostream& os, Tuple&& t, std::index_sequence<Idx...>)
3023  {
3024  os << "(";
3025  refl::util::ignore((os << std::get<Idx>(t))...);
3026  os << ")";
3027  }
3028 
3029  template <typename... Ts>
3030  void write_impl(std::ostream& os, const std::tuple<Ts...>& t)
3031  {
3032  write_impl(os, t, std::make_index_sequence<sizeof...(Ts)>{});
3033  }
3034 
3035  template <typename K, typename V>
3036  void write_impl(std::ostream& os, const std::pair<K, V>& t);
3037 
3038  template <typename K, typename V>
3039  void write_impl(std::ostream& os, const std::pair<K, V>& t)
3040  {
3041  os << "(";
3042  write(os, t.first);
3043  os << ", ";
3044  write(os, t.second);
3045  os << ")";
3046  }
3047 
3048  template <typename T, typename D>
3049  void write_impl(std::ostream& os, const std::unique_ptr<T, D>& t)
3050  {
3051  runtime::debug(os, t.get(), true);
3052  }
3053 
3054  template <typename T>
3055  void write_impl(std::ostream& os, const std::shared_ptr<T>& t)
3056  {
3057  runtime::debug(os, t.get(), true);
3058  }
3059 
3060  template <typename T>
3061  void write_impl(std::ostream& os, const std::weak_ptr<T>& t)
3062  {
3063  runtime::debug(os, t.lock().get(), true);
3064  }
3065 
3066  // Dispatches to the appropriate write_impl.
3067  constexpr auto write = [](std::ostream & os, auto&& t) -> void
3068  {
3069  write_impl(os, t);
3070  };
3071 } // namespace refl::detail
3072 
3073 // Custom reflection information for
3074 // some common built-in types (std::basic_string, std::tuple, std::pair).
3075 
3076 #ifndef REFL_NO_STD_SUPPORT
3077 
3078 REFL_TYPE(std::exception, debug{ refl::detail::write })
3079  REFL_FUNC(what, property{ })
3080 REFL_END
3081 
3082 REFL_TYPE(std::string, debug{ refl::detail::write })
3083  REFL_FUNC(size, property{ })
3084  REFL_FUNC(data, property{ })
3085 REFL_END
3086 
3088  (typename Elem, typename Traits, typename Alloc),
3090  debug{ refl::detail::write })
3091  REFL_FUNC(size, property{ })
3092  REFL_FUNC(data, property{ })
3093 REFL_END
3094 
3095 #ifdef __cpp_lib_string_view
3096 
3098  (typename Elem, typename Traits),
3100  debug{ refl::detail::write })
3101  REFL_FUNC(size, property{ })
3102  REFL_FUNC(data, property{ })
3103 REFL_END
3104 
3105 #endif
3106 
3108  (typename... Ts),
3110  debug{ refl::detail::write })
3111 REFL_END
3112 
3114  (typename T, typename D),
3116  debug{ refl::detail::write })
3117 REFL_END
3118 
3120  (typename T),
3122  debug{ refl::detail::write })
3123 REFL_END
3124 
3126  (typename K, typename V),
3127  (std::pair<K, V>),
3128  debug{ refl::detail::write })
3129 REFL_END
3130 
3131 #endif // REFL_NO_STD_SUPPORT
3132 
3133 #ifndef REFL_NO_AUTO_MACRO
3134 
3135 #define REFL_DETAIL_EXPAND(x) x
3136 #define REFL_DETAIL_FOR_EACH_0(...)
3137 #define REFL_DETAIL_FOR_EACH_1(what, x, ...) what(x)
3138 #define REFL_DETAIL_FOR_EACH_2(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_1(what, __VA_ARGS__))
3139 #define REFL_DETAIL_FOR_EACH_3(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_2(what, __VA_ARGS__))
3140 #define REFL_DETAIL_FOR_EACH_4(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_3(what, __VA_ARGS__))
3141 #define REFL_DETAIL_FOR_EACH_5(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_4(what, __VA_ARGS__))
3142 #define REFL_DETAIL_FOR_EACH_6(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_5(what, __VA_ARGS__))
3143 #define REFL_DETAIL_FOR_EACH_7(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_6(what, __VA_ARGS__))
3144 #define REFL_DETAIL_FOR_EACH_8(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_7(what, __VA_ARGS__))
3145 #define REFL_DETAIL_FOR_EACH_9(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_8(what, __VA_ARGS__))
3146 #define REFL_DETAIL_FOR_EACH_10(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_9(what, __VA_ARGS__))
3147 #define REFL_DETAIL_FOR_EACH_11(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_10(what, __VA_ARGS__))
3148 #define REFL_DETAIL_FOR_EACH_12(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_11(what, __VA_ARGS__))
3149 #define REFL_DETAIL_FOR_EACH_13(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_12(what, __VA_ARGS__))
3150 #define REFL_DETAIL_FOR_EACH_14(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_13(what, __VA_ARGS__))
3151 #define REFL_DETAIL_FOR_EACH_15(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_14(what, __VA_ARGS__))
3152 #define REFL_DETAIL_FOR_EACH_16(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_15(what, __VA_ARGS__))
3153 #define REFL_DETAIL_FOR_EACH_17(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_16(what, __VA_ARGS__))
3154 #define REFL_DETAIL_FOR_EACH_18(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_17(what, __VA_ARGS__))
3155 #define REFL_DETAIL_FOR_EACH_19(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_18(what, __VA_ARGS__))
3156 #define REFL_DETAIL_FOR_EACH_20(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_19(what, __VA_ARGS__))
3157 #define REFL_DETAIL_FOR_EACH_21(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_20(what, __VA_ARGS__))
3158 #define REFL_DETAIL_FOR_EACH_22(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_21(what, __VA_ARGS__))
3159 #define REFL_DETAIL_FOR_EACH_23(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_22(what, __VA_ARGS__))
3160 #define REFL_DETAIL_FOR_EACH_24(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_23(what, __VA_ARGS__))
3161 #define REFL_DETAIL_FOR_EACH_25(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_24(what, __VA_ARGS__))
3162 #define REFL_DETAIL_FOR_EACH_26(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_25(what, __VA_ARGS__))
3163 #define REFL_DETAIL_FOR_EACH_27(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_26(what, __VA_ARGS__))
3164 #define REFL_DETAIL_FOR_EACH_28(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_27(what, __VA_ARGS__))
3165 #define REFL_DETAIL_FOR_EACH_29(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_28(what, __VA_ARGS__))
3166 #define REFL_DETAIL_FOR_EACH_30(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_29(what, __VA_ARGS__))
3167 #define REFL_DETAIL_FOR_EACH_31(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_30(what, __VA_ARGS__))
3168 #define REFL_DETAIL_FOR_EACH_32(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_31(what, __VA_ARGS__))
3169 #define REFL_DETAIL_FOR_EACH_33(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_32(what, __VA_ARGS__))
3170 #define REFL_DETAIL_FOR_EACH_34(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_33(what, __VA_ARGS__))
3171 #define REFL_DETAIL_FOR_EACH_35(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_34(what, __VA_ARGS__))
3172 #define REFL_DETAIL_FOR_EACH_36(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_35(what, __VA_ARGS__))
3173 #define REFL_DETAIL_FOR_EACH_37(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_36(what, __VA_ARGS__))
3174 #define REFL_DETAIL_FOR_EACH_38(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_37(what, __VA_ARGS__))
3175 #define REFL_DETAIL_FOR_EACH_39(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_38(what, __VA_ARGS__))
3176 #define REFL_DETAIL_FOR_EACH_40(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_39(what, __VA_ARGS__))
3177 #define REFL_DETAIL_FOR_EACH_41(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_40(what, __VA_ARGS__))
3178 #define REFL_DETAIL_FOR_EACH_42(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_41(what, __VA_ARGS__))
3179 #define REFL_DETAIL_FOR_EACH_43(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_42(what, __VA_ARGS__))
3180 #define REFL_DETAIL_FOR_EACH_44(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_43(what, __VA_ARGS__))
3181 #define REFL_DETAIL_FOR_EACH_45(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_44(what, __VA_ARGS__))
3182 #define REFL_DETAIL_FOR_EACH_46(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_45(what, __VA_ARGS__))
3183 #define REFL_DETAIL_FOR_EACH_47(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_46(what, __VA_ARGS__))
3184 #define REFL_DETAIL_FOR_EACH_48(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_47(what, __VA_ARGS__))
3185 #define REFL_DETAIL_FOR_EACH_49(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_48(what, __VA_ARGS__))
3186 #define REFL_DETAIL_FOR_EACH_50(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_49(what, __VA_ARGS__))
3187 #define REFL_DETAIL_FOR_EACH_51(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_50(what, __VA_ARGS__))
3188 #define REFL_DETAIL_FOR_EACH_52(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_51(what, __VA_ARGS__))
3189 #define REFL_DETAIL_FOR_EACH_53(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_52(what, __VA_ARGS__))
3190 #define REFL_DETAIL_FOR_EACH_54(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_53(what, __VA_ARGS__))
3191 #define REFL_DETAIL_FOR_EACH_55(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_54(what, __VA_ARGS__))
3192 #define REFL_DETAIL_FOR_EACH_56(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_55(what, __VA_ARGS__))
3193 #define REFL_DETAIL_FOR_EACH_57(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_56(what, __VA_ARGS__))
3194 #define REFL_DETAIL_FOR_EACH_58(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_57(what, __VA_ARGS__))
3195 #define REFL_DETAIL_FOR_EACH_59(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_58(what, __VA_ARGS__))
3196 #define REFL_DETAIL_FOR_EACH_60(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_59(what, __VA_ARGS__))
3197 #define REFL_DETAIL_FOR_EACH_61(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_60(what, __VA_ARGS__))
3198 #define REFL_DETAIL_FOR_EACH_62(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_61(what, __VA_ARGS__))
3199 #define REFL_DETAIL_FOR_EACH_63(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_62(what, __VA_ARGS__))
3200 #define REFL_DETAIL_FOR_EACH_64(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_63(what, __VA_ARGS__))
3201 #define REFL_DETAIL_FOR_EACH_65(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_64(what, __VA_ARGS__))
3202 #define REFL_DETAIL_FOR_EACH_66(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_65(what, __VA_ARGS__))
3203 #define REFL_DETAIL_FOR_EACH_67(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_66(what, __VA_ARGS__))
3204 #define REFL_DETAIL_FOR_EACH_68(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_67(what, __VA_ARGS__))
3205 #define REFL_DETAIL_FOR_EACH_69(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_68(what, __VA_ARGS__))
3206 #define REFL_DETAIL_FOR_EACH_70(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_69(what, __VA_ARGS__))
3207 #define REFL_DETAIL_FOR_EACH_71(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_70(what, __VA_ARGS__))
3208 #define REFL_DETAIL_FOR_EACH_72(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_71(what, __VA_ARGS__))
3209 #define REFL_DETAIL_FOR_EACH_73(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_72(what, __VA_ARGS__))
3210 #define REFL_DETAIL_FOR_EACH_74(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_73(what, __VA_ARGS__))
3211 #define REFL_DETAIL_FOR_EACH_75(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_74(what, __VA_ARGS__))
3212 #define REFL_DETAIL_FOR_EACH_76(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_75(what, __VA_ARGS__))
3213 #define REFL_DETAIL_FOR_EACH_77(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_76(what, __VA_ARGS__))
3214 #define REFL_DETAIL_FOR_EACH_78(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_77(what, __VA_ARGS__))
3215 #define REFL_DETAIL_FOR_EACH_79(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_78(what, __VA_ARGS__))
3216 #define REFL_DETAIL_FOR_EACH_80(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_79(what, __VA_ARGS__))
3217 #define REFL_DETAIL_FOR_EACH_81(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_80(what, __VA_ARGS__))
3218 #define REFL_DETAIL_FOR_EACH_82(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_81(what, __VA_ARGS__))
3219 #define REFL_DETAIL_FOR_EACH_83(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_82(what, __VA_ARGS__))
3220 #define REFL_DETAIL_FOR_EACH_84(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_83(what, __VA_ARGS__))
3221 #define REFL_DETAIL_FOR_EACH_85(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_84(what, __VA_ARGS__))
3222 #define REFL_DETAIL_FOR_EACH_86(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_85(what, __VA_ARGS__))
3223 #define REFL_DETAIL_FOR_EACH_87(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_86(what, __VA_ARGS__))
3224 #define REFL_DETAIL_FOR_EACH_88(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_87(what, __VA_ARGS__))
3225 #define REFL_DETAIL_FOR_EACH_89(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_88(what, __VA_ARGS__))
3226 #define REFL_DETAIL_FOR_EACH_90(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_89(what, __VA_ARGS__))
3227 #define REFL_DETAIL_FOR_EACH_91(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_90(what, __VA_ARGS__))
3228 #define REFL_DETAIL_FOR_EACH_92(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_91(what, __VA_ARGS__))
3229 #define REFL_DETAIL_FOR_EACH_93(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_92(what, __VA_ARGS__))
3230 #define REFL_DETAIL_FOR_EACH_94(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_93(what, __VA_ARGS__))
3231 #define REFL_DETAIL_FOR_EACH_95(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_94(what, __VA_ARGS__))
3232 #define REFL_DETAIL_FOR_EACH_96(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_95(what, __VA_ARGS__))
3233 #define REFL_DETAIL_FOR_EACH_97(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_96(what, __VA_ARGS__))
3234 #define REFL_DETAIL_FOR_EACH_98(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_97(what, __VA_ARGS__))
3235 #define REFL_DETAIL_FOR_EACH_99(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_98(what, __VA_ARGS__))
3236 #define REFL_DETAIL_FOR_EACH_100(what, x, ...) what(x) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_99(what, __VA_ARGS__))
3237 
3238 #define REFL_DETAIL_FOR_EACH_NARG(...) REFL_DETAIL_FOR_EACH_NARG_(__VA_ARGS__, REFL_DETAIL_FOR_EACH_RSEQ_N())
3239 #define REFL_DETAIL_FOR_EACH_NARG_(...) REFL_DETAIL_EXPAND(REFL_DETAIL_FOR_EACH_ARG_N(__VA_ARGS__))
3240 #define REFL_DETAIL_FOR_EACH_ARG_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, _65, _66, _67, _68, _69, _70, _71, _72, _73, _74, _75, _76, _77, _78, _79, _80, _81, _82, _83, _84, _85, _86, _87, _88, _89, _90, _91, _92, _93, _94, _95, _96, _97, _98, _99, _100, N, ...) N
3241 #define REFL_DETAIL_FOR_EACH_RSEQ_N() 100, 99, 98, 97, 96, 95, 94, 93, 92, 91, 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, 79, 78, 77, 76, 75, 74, 73, 72, 71, 70, 69, 68, 67, 66, 65, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
3242 #define REFL_DETAIL_CONCATENATE(x, y) x##y
3243 #define REFL_DETAIL_FOR_EACH_(N, what, ...) REFL_DETAIL_EXPAND(REFL_DETAIL_CONCATENATE(REFL_DETAIL_FOR_EACH_, N)(what, __VA_ARGS__))
3244 #define REFL_DETAIL_FOR_EACH(what, ...) REFL_DETAIL_FOR_EACH_(REFL_DETAIL_FOR_EACH_NARG(__VA_ARGS__), what, __VA_ARGS__)
3245 
3246 // Intellisense does not work nicely with passing variadic parameters (for the attributes)
3247 // through all of the macro expansions and causes differently named member declarations to be
3248 // used during code inspection.
3249 #ifdef __INTELLISENSE__
3250 
3251 #define REFL_DETAIL_EX_1_type(X, ...) REFL_TYPE(X)
3252 #define REFL_DETAIL_EX_1_template(X, Y, ...) REFL_TEMPLATE(X, Y)
3253 #define REFL_DETAIL_EX_1_field(X, ...) REFL_FIELD(X)
3254 #define REFL_DETAIL_EX_1_func(X, ...) REFL_FUNC(X)
3255 
3256 #else // !defined(__INTELLISENSE__)
3257 
3258 #define REFL_DETAIL_EX_1_type(...) REFL_DETAIL_EX_EXPAND(REFL_DETAIL_EX_DEFER(REFL_TYPE)(__VA_ARGS__))
3259 #define REFL_DETAIL_EX_1_template(...) REFL_DETAIL_EX_EXPAND(REFL_DETAIL_EX_DEFER(REFL_TEMPLATE)(__VA_ARGS__))
3260 #define REFL_DETAIL_EX_1_field(...) REFL_DETAIL_EX_EXPAND(REFL_DETAIL_EX_DEFER(REFL_FIELD)(__VA_ARGS__))
3261 #define REFL_DETAIL_EX_1_func(...) REFL_DETAIL_EX_EXPAND(REFL_DETAIL_EX_DEFER(REFL_FUNC)(__VA_ARGS__))
3262 
3263 #endif // __INTELLISENSE__
3264 
3265 #define REFL_DETAIL_EX_(Specifier, ...) REFL_DETAIL_EX_1_##Specifier __VA_ARGS__
3266 
3267 #define REFL_DETAIL_EX_EMPTY()
3268 #define REFL_DETAIL_EX_DEFER(Id) Id REFL_DETAIL_EX_EMPTY()
3269 #define REFL_DETAIL_EX_EXPAND(...) __VA_ARGS__
3270 
3271 #define REFL_DETAIL_EX_END() REFL_END
3272 
3273 #define REFL_AUTO(...) REFL_DETAIL_FOR_EACH(REFL_DETAIL_EX_, __VA_ARGS__) REFL_DETAIL_EX_EXPAND(REFL_DETAIL_EX_DEFER(REFL_DETAIL_EX_END)())
3274 
3275 #endif // !defined(REFL_NO_AUTO_MACRO)
3276 
3277 #endif // REFL_INCLUDE_HPP
refl::reflect
constexpr type_descriptor< T > reflect(const T &) noexcept
Definition: refl.hpp:1588
refl::attr::debug::write
const F write
Definition: refl.hpp:1963
refl::descriptor::field_descriptor::operator()
constexpr auto operator()(Args &&... args) const noexcept -> decltype(invoker::invoke(std::forward< Args >(args)...))
Definition: refl.hpp:1409
refl::util::get
constexpr const auto & get(const std::tuple< Ts... > &ts) noexcept
Definition: refl.hpp:1897
refl::descriptor::field_descriptor::get
static constexpr decltype(auto) get() noexcept
Definition: refl.hpp:1395
refl::trait::remove_qualifiers::type
std::remove_cv_t< std::remove_reference_t< T > > type
Definition: refl.hpp:527
refl::trait::is_property
Definition: refl.hpp:2006
refl::runtime::debug_all
void debug_all(std::ostream &os, const Ts &... values)
Definition: refl.hpp:2638
refl::descriptor::is_property
constexpr bool is_property(const T t) noexcept
Definition: refl.hpp:2094
refl::runtime::debug
void debug(std::ostream &os, const T &value, [[maybe_unused]] bool compact)
Definition: refl.hpp:2626
refl::util::count_if
constexpr size_t count_if(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1777
refl::runtime::proxy::target_type
Target target_type
Definition: refl.hpp:2421
refl::descriptor::has_bases
constexpr auto has_bases(const T t) noexcept
Definition: refl.hpp:2173
refl::util::get
constexpr const T & get(const std::tuple< Ts... > &ts) noexcept
Definition: refl.hpp:1911
refl::util::apply
constexpr auto apply(type_list< Ts... >, F &&f)
Definition: refl.hpp:1856
refl::util::const_string::size
static constexpr size_t size
Definition: refl.hpp:109
refl::runtime::debug_all_str
std::string debug_all_str(const Ts &... values)
Definition: refl.hpp:2660
refl::util::operator+
constexpr const_string< N+M - 1 > operator+(const char(&a)[N], const const_string< M > &b) noexcept
Definition: refl.hpp:265
refl::trait::is_instance_of
Definition: refl.hpp:1029
refl::util::to_array
constexpr std::array< T, 0 > to_array(const std::tuple<> &) noexcept
Definition: refl.hpp:1648
refl::is_reflectable
constexpr bool is_reflectable() noexcept
Definition: refl.hpp:1567
refl::trait::filter< Predicate, type_list< Ts... > >::type
detail::filter< Predicate >::template apply< type_list< Ts... > > type
Definition: refl.hpp:939
refl::descriptor::function_descriptor::operator()
constexpr auto operator()(Args &&... args) const -> decltype(invoke(std::declval< Args >()...))
Definition: refl.hpp:1471
REFL_TEMPLATE
#define REFL_TEMPLATE(TemplateDeclaration, TypeName,...)
Definition: refl.hpp:2828
refl::descriptor::get_property
constexpr attr::property get_property(const T t) noexcept
Definition: refl.hpp:2106
refl::descriptor::get_debug_name
const char * get_debug_name(const T &t)
Definition: refl.hpp:2199
refl::util::const_string::str
std::string str() const noexcept
Definition: refl.hpp:167
refl::attr
Contains the definitions of the built-in attributes.
Definition: refl.hpp:1133
refl::attr::usage
Contains a number of constraints applicable to refl-cpp attributes.
Definition: refl.hpp:1142
refl::util::make_const
constexpr const T & make_const(T &value) noexcept
Definition: refl.hpp:1628
refl::attr::usage::any
Definition: refl.hpp:1172
refl::descriptor::get_attribute
constexpr const A & get_attribute(const T t) noexcept
Definition: refl.hpp:2073
refl::trait::contains_base
Definition: refl.hpp:1104
refl::util::find_first
constexpr auto find_first(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1820
refl::descriptor::function_descriptor::can_resolve
static constexpr bool can_resolve()
Definition: refl.hpp:1491
refl::attr::debug::debug
constexpr debug(F write)
Definition: refl.hpp:1965
refl::util::make_const_string
constexpr const_string< 0 > make_const_string() noexcept
Definition: refl.hpp:216
refl::util::operator==
constexpr bool operator==(const const_string< N > &a, const const_string< M > &b) noexcept
Definition: refl.hpp:276
refl::util::type_list::size
static constexpr intptr_t size
Definition: refl.hpp:392
refl::util::const_string::substr
constexpr auto substr() const noexcept
Definition: refl.hpp:176
refl::util::find_one
constexpr auto find_one(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1833
refl::descriptor::member_descriptor_base::member
refl_impl::metadata::type_info__< T >::template member< N > member
Definition: refl.hpp:1300
refl::trait::is_reflectable
Definition: refl.hpp:557
refl::util::ignore
constexpr int ignore(Ts &&...) noexcept
Definition: refl.hpp:1600
refl::util::const_string
Definition: refl.hpp:103
refl::trait::is_proxy::value
static constexpr bool value
Definition: refl.hpp:2463
refl::descriptor::is_readable
constexpr bool is_readable(const T) noexcept
Definition: refl.hpp:2124
refl::attr::base_types::list
static constexpr list_type list
Definition: refl.hpp:1981
refl::util::get
constexpr auto & get(std::tuple< Ts... > &ts) noexcept
Definition: refl.hpp:1890
refl::util
Contains utility types and functions for working with those types.
Definition: refl.hpp:81
refl::util::const_string::string
operator std::string() const noexcept
Definition: refl.hpp:151
refl::trait::as_type_list< T< Ts... > >::type
type_list< Ts... > type
Definition: refl.hpp:682
REFL_DETAIL_GROUP
#define REFL_DETAIL_GROUP(...)
Definition: refl.hpp:2779
refl::descriptor::field_descriptor::get
static constexpr decltype(auto) get(U &&target) noexcept
Definition: refl.hpp:1402
refl::trait::is_instance
Definition: refl.hpp:984
refl::descriptor::function_descriptor
Represents a reflected function.
Definition: refl.hpp:1447
refl::util::operator+
constexpr const_string< N+M - 1 > operator+(const const_string< N > &a, const char(&b)[M]) noexcept
Definition: refl.hpp:254
refl::descriptor::function_descriptor::is_resolved
static constexpr bool is_resolved
Definition: refl.hpp:1485
refl::descriptor::type_descriptor::type
T type
Definition: refl.hpp:1540
refl::trait::is_type_v
constexpr bool is_type_v
Definition: refl.hpp:1268
refl::descriptor::member_descriptor_base::declarator
static constexpr type_descriptor< T > declarator
Definition: refl.hpp:1314
refl::util::operator!=
constexpr bool operator!=(const char(&a)[N], const const_string< M > &b) noexcept
Definition: refl.hpp:341
REFL_DETAIL_FORCE_EBO
#define REFL_DETAIL_FORCE_EBO
Definition: refl.hpp:2297
refl::descriptor::field_descriptor::pointer
static constexpr auto pointer
Definition: refl.hpp:1385
refl::descriptor::member_descriptor_base::attribute_types
trait::as_type_list_t< std::remove_cv_t< decltype(member::attributes)> > attribute_types
Definition: refl.hpp:1311
refl::trait
Provides type-level operations for refl-cpp related use-cases.
Definition: refl.hpp:518
refl::trait::is_type
Definition: refl.hpp:1259
refl::member
Contains tag types denoting the different types of reflectable members.
Definition: refl.hpp:493
refl::runtime::proxy::proxy
constexpr proxy() noexcept
Definition: refl.hpp:2429
refl::descriptor::function_descriptor::pointer
static constexpr auto pointer
Definition: refl.hpp:1479
refl::runtime::debug_str
std::string debug_str(const T &value, bool compact=false)
Definition: refl.hpp:2649
refl::member::field
Definition: refl.hpp:501
refl::descriptor::member_descriptor_base
The base type for member descriptors.
Definition: refl.hpp:1296
refl::util::operator==
constexpr bool operator==(const const_string< N > &a, const char(&b)[M]) noexcept
Definition: refl.hpp:308
refl::trait::is_descriptor
Definition: refl.hpp:1274
refl::util::const_string::npos
static constexpr size_t npos
Definition: refl.hpp:106
refl::descriptor::member_descriptor_base::declaring_type
T declaring_type
Definition: refl.hpp:1305
refl::attr::base_types::list_type
type_list< Ts... > list_type
Definition: refl.hpp:1978
REFL_DETAIL_STR
#define REFL_DETAIL_STR(...)
Definition: refl.hpp:2777
refl::attr::usage::member
Definition: refl.hpp:1166
refl::descriptor::is_function
constexpr bool is_function(const T) noexcept
Definition: refl.hpp:2035
refl::attr::property::property
constexpr property(const char *friendly_name) noexcept
Definition: refl.hpp:1951
refl::descriptor::member_descriptor_base::name
static constexpr auto name
Definition: refl.hpp:1317
refl::is_reflectable
constexpr bool is_reflectable(const T &) noexcept
Definition: refl.hpp:1574
refl::util::to_array
constexpr std::array< T, sizeof...(Ts)> to_array(const std::tuple< Ts... > &tuple) noexcept
Definition: refl.hpp:1639
refl::util::type_list
Definition: refl.hpp:389
refl::util::map_to_array
constexpr auto map_to_array(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1726
refl::descriptor::field_descriptor::is_writable
static constexpr bool is_writable
Definition: refl.hpp:1382
refl::trait::is_member
Definition: refl.hpp:1200
refl::attr::usage::type
Definition: refl.hpp:1148
refl::util::operator!=
constexpr bool operator!=(const const_string< N > &a, const const_string< M > &b) noexcept
Definition: refl.hpp:297
refl::trait::reverse
Definition: refl.hpp:810
refl::descriptor::field_descriptor::value_type
member::value_type value_type
Definition: refl.hpp:1371
refl
The top-level refl-cpp namespace It contains a few core refl-cpp namespaces and directly exposes core...
Definition: refl.hpp:76
refl::util::contains
constexpr auto contains(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1846
refl::util::accumulate
constexpr auto accumulate(type_list< T, Ts... >, F &&f, R &&initial_value)
Definition: refl.hpp:1761
refl::util::get_instance
constexpr const auto & get_instance(const std::tuple< Ts... > &ts) noexcept
Definition: refl.hpp:1927
refl::descriptor::function_descriptor::resolve
static constexpr auto resolve()
Definition: refl.hpp:1501
refl::descriptor::is_field
constexpr bool is_field(const T) noexcept
Definition: refl.hpp:2024
refl::descriptor::get_display_name
const char * get_display_name(const T &t) noexcept
Definition: refl.hpp:2285
refl::descriptor::function_descriptor::invoke
static constexpr auto invoke(Args &&... args) -> decltype(member::invoke(std::declval< Args >()...))
Definition: refl.hpp:1460
refl::descriptor
Contains the basic reflection primitives as well as functions operating on those primitives.
Definition: refl.hpp:1176
refl::util::accumulate
constexpr R accumulate(type_list<>, F &&, R &&initial_value)
Definition: refl.hpp:1749
refl::runtime::proxy
A proxy object that has a static interface identical to the reflected functions and fields of the tar...
Definition: refl.hpp:2413
refl::descriptor::has_attribute
constexpr bool has_attribute(const T) noexcept
Definition: refl.hpp:2055
refl::attr::property::property
constexpr property() noexcept
Definition: refl.hpp:1946
refl::reflect
constexpr type_descriptor< T > reflect() noexcept
Definition: refl.hpp:1581
refl::util::operator!=
constexpr bool operator!=(const const_string< N > &a, const char(&b)[M]) noexcept
Definition: refl.hpp:319
refl::descriptor::field_descriptor::is_static
static constexpr bool is_static
Definition: refl.hpp:1379
refl::util::const_string::c_str
constexpr const char * c_str() const noexcept
Definition: refl.hpp:159
REFL_DETAIL_ATTRIBUTES
#define REFL_DETAIL_ATTRIBUTES(DeclType,...)
Definition: refl.hpp:2786
refl::util::filter
constexpr auto filter(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1810
refl::runtime::invoke
U invoke(T &&target, const char *name, Args &&... args)
Definition: refl.hpp:2674
refl::attr::usage::field
Definition: refl.hpp:1160
refl::trait::append
Definition: refl.hpp:844
refl::util::operator+
constexpr const_string< N+M > operator+(const const_string< N > &a, const const_string< M > &b) noexcept
Definition: refl.hpp:238
refl::util::map_to_tuple
constexpr auto map_to_tuple(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1716
refl::descriptor::type_descriptor::members
static constexpr member_list< T > members
Definition: refl.hpp:1549
refl::trait::is_container
Definition: refl.hpp:585
refl::util::get
constexpr T & get(std::tuple< Ts... > &ts) noexcept
Definition: refl.hpp:1904
refl::trait::contains
Definition: refl.hpp:1072
refl::trait::contains_instance
Definition: refl.hpp:1088
refl::trait::is_field
Definition: refl.hpp:1222
REFL_DETAIL_TYPE_BODY
#define REFL_DETAIL_TYPE_BODY(TypeName,...)
Definition: refl.hpp:2792
refl::util::to_tuple
constexpr auto to_tuple(const std::array< T, N > &array) noexcept
Definition: refl.hpp:1667
refl::util::operator==
constexpr bool operator==(const char(&a)[N], const const_string< M > &b) noexcept
Definition: refl.hpp:330
refl::descriptor::type_descriptor::name
static constexpr const auto name
Definition: refl.hpp:1552
refl::descriptor::field_descriptor
Represents a reflected field.
Definition: refl.hpp:1368
REFL_DETAIL_STR_IMPL
#define REFL_DETAIL_STR_IMPL(...)
Definition: refl.hpp:2775
refl::descriptor::type_descriptor::member_types
member_list< T > member_types
Definition: refl.hpp:1543
refl::util::make_const_string
constexpr const_string< N - 1 > make_const_string(const char(&str)[N]) noexcept
Definition: refl.hpp:227
refl::util::const_string::const_string
constexpr const_string() noexcept
Definition: refl.hpp:119
refl::descriptor::get_bases
constexpr auto get_bases(const T t) noexcept
Definition: refl.hpp:2186
refl::util::const_string::const_string
constexpr const_string(const char(&data)[N+1]) noexcept
Definition: refl.hpp:135
refl::trait::map< Mapper, type_list< Ts... > >::type
detail::map< Mapper >::template apply< type_list< Ts... > > type
Definition: refl.hpp:959
refl::attr::base_types
Definition: refl.hpp:1975
refl::util::const_string::operator const char *
constexpr operator const char *() const noexcept
Definition: refl.hpp:143
refl::descriptor::type_descriptor::attributes
static constexpr const auto attributes
Definition: refl.hpp:1555
refl::member::function
Definition: refl.hpp:509
refl::trait::remove_qualifiers
Definition: refl.hpp:525
REFL_TYPE
#define REFL_TYPE(TypeName,...)
Definition: refl.hpp:2811
refl::descriptor::member_descriptor_base::attributes
static constexpr auto attributes
Definition: refl.hpp:1320
refl::util::make_const
constexpr const T & make_const(const T &value) noexcept
Definition: refl.hpp:1619
refl::util::const_string::data
char data[N+1]
Definition: refl.hpp:114
refl::trait::is_function
Definition: refl.hpp:1244
refl::descriptor::member_descriptor_base::member_type
member::member_type member_type
Definition: refl.hpp:1308
refl::descriptor::type_descriptor::attribute_types
trait::as_type_list_t< std::remove_cv_t< decltype(type_info::attributes)> > attribute_types
Definition: refl.hpp:1546
refl::attr::property::friendly_name
const std::optional< const char * > friendly_name
Definition: refl.hpp:1944
refl::runtime
Contains utilities that can have runtime-overhead (like proxy, debug, invoke)
Definition: refl.hpp:2304
refl::attr::debug
Definition: refl.hpp:1961
refl::util::get_instance
constexpr auto & get_instance(std::tuple< Ts... > &ts) noexcept
Definition: refl.hpp:1918
refl::descriptor::is_type
constexpr bool is_type(const T) noexcept
Definition: refl.hpp:2046
refl::descriptor::is_writable
constexpr bool is_writable(const T) noexcept
Definition: refl.hpp:2144
refl::util::identity
constexpr decltype(auto) identity(T &&t) noexcept
Definition: refl.hpp:1610
refl::attr::usage::function
Definition: refl.hpp:1154
refl::util::const_string::const_string
constexpr const_string(const const_string< N > &other) noexcept
Definition: refl.hpp:127
refl::attr::property
Definition: refl.hpp:1942
refl::descriptor::get_attribute
constexpr const auto & get_attribute(const T t) noexcept
Definition: refl.hpp:2082
refl::util::for_each
constexpr void for_each(type_list< Ts... > list, F &&f)
Definition: refl.hpp:1736