members.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. #ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED
  2. #define BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED
  3. // Copyright 2020 Peter Dimov
  4. // Distributed under the Boost Software License, Version 1.0.
  5. // https://www.boost.org/LICENSE_1_0.txt
  6. #include <boost/describe/modifiers.hpp>
  7. #include <boost/describe/bases.hpp>
  8. #include <boost/describe/detail/void_t.hpp>
  9. #include <boost/describe/detail/cx_streq.hpp>
  10. #include <boost/describe/detail/config.hpp>
  11. #if defined(BOOST_DESCRIBE_CXX11)
  12. #include <boost/mp11/algorithm.hpp>
  13. #include <boost/mp11/utility.hpp>
  14. #include <boost/mp11/integral.hpp>
  15. #include <boost/mp11/list.hpp>
  16. #include <boost/mp11/bind.hpp>
  17. #include <type_traits>
  18. namespace boost
  19. {
  20. namespace describe
  21. {
  22. namespace detail
  23. {
  24. // _describe_members<T>
  25. template<class T> using _describe_public_members = decltype( boost_public_member_descriptor_fn( static_cast<T**>(0) ) );
  26. template<class T> using _describe_protected_members = decltype( boost_protected_member_descriptor_fn( static_cast<T**>(0) ) );
  27. template<class T> using _describe_private_members = decltype( boost_private_member_descriptor_fn( static_cast<T**>(0) ) );
  28. template<class T> using _describe_members = mp11::mp_append<_describe_public_members<T>, _describe_protected_members<T>, _describe_private_members<T>>;
  29. // describe_inherited_members<T>
  30. // T: type
  31. // V: list of virtual bases visited so far
  32. template<class T, class V> struct describe_inherited_members_impl;
  33. template<class T, class V> using describe_inherited_members = typename describe_inherited_members_impl<T, V>::type;
  34. // L: list of base class descriptors
  35. // T: derived type
  36. // V: list of virtual bases visited so far
  37. template<class L, class T, class V> struct describe_inherited_members2_impl;
  38. template<class L, class T, class V> using describe_inherited_members2 = typename describe_inherited_members2_impl<L, T, V>::type;
  39. template<class T, class V> struct describe_inherited_members_impl
  40. {
  41. using R1 = describe_inherited_members2<describe_bases<T, mod_any_access>, T, V>;
  42. using R2 = _describe_members<T>;
  43. using type = mp11::mp_append<R1, R2>;
  44. };
  45. template<template<class...> class L, class T, class V> struct describe_inherited_members2_impl<L<>, T, V>
  46. {
  47. using type = L<>;
  48. };
  49. template<class D1, class D2> using name_matches = mp11::mp_bool< cx_streq( D1::name, D2::name ) >;
  50. template<class D, class L> using name_is_hidden = mp11::mp_any_of_q<L, mp11::mp_bind_front<name_matches, D>>;
  51. constexpr unsigned cx_max( unsigned m1, unsigned m2 )
  52. {
  53. return m1 > m2? m1: m2;
  54. }
  55. template<class T, unsigned Bm> struct update_modifiers
  56. {
  57. template<class D> struct fn
  58. {
  59. using L = _describe_members<T>;
  60. static constexpr unsigned hidden = name_is_hidden<D, L>::value? mod_hidden: 0;
  61. static constexpr unsigned mods = D::modifiers;
  62. static constexpr unsigned access = cx_max( mods & mod_any_access, Bm & mod_any_access );
  63. static constexpr decltype(D::pointer) pointer = D::pointer;
  64. static constexpr decltype(D::name) name = D::name;
  65. static constexpr unsigned modifiers = ( mods & ~mod_any_access ) | access | mod_inherited | hidden;
  66. };
  67. };
  68. #ifndef __cpp_inline_variables
  69. template<class T, unsigned Bm> template<class D> constexpr decltype(D::pointer) update_modifiers<T, Bm>::fn<D>::pointer;
  70. template<class T, unsigned Bm> template<class D> constexpr decltype(D::name) update_modifiers<T, Bm>::fn<D>::name;
  71. template<class T, unsigned Bm> template<class D> constexpr unsigned update_modifiers<T, Bm>::fn<D>::modifiers;
  72. #endif
  73. template<class D> struct gather_virtual_bases_impl;
  74. template<class D> using gather_virtual_bases = typename gather_virtual_bases_impl<D>::type;
  75. template<class D> struct gather_virtual_bases_impl
  76. {
  77. using B = typename D::type;
  78. static constexpr unsigned M = D::modifiers;
  79. using R1 = mp11::mp_transform<gather_virtual_bases, describe_bases<B, mod_any_access>>;
  80. using R2 = mp11::mp_apply<mp11::mp_append, R1>;
  81. using type = mp11::mp_if_c<(M & mod_virtual) != 0, mp11::mp_push_front<R2, B>, R2>;
  82. };
  83. template<template<class...> class L, class D1, class... D, class T, class V> struct describe_inherited_members2_impl<L<D1, D...>, T, V>
  84. {
  85. using B = typename D1::type;
  86. static constexpr unsigned M = D1::modifiers;
  87. using R1 = mp11::mp_if_c<(M & mod_virtual) && mp11::mp_contains<V, B>::value, L<>, describe_inherited_members<B, V>>;
  88. using R2 = mp11::mp_transform_q<update_modifiers<T, M>, R1>;
  89. using V2 = mp11::mp_append<V, gather_virtual_bases<D1>>;
  90. using R3 = describe_inherited_members2<L<D...>, T, V2>;
  91. using type = mp11::mp_append<R2, R3>;
  92. };
  93. // describe_members<T, M>
  94. template<class T, unsigned M> using describe_members = mp11::mp_eval_if_c<(M & mod_inherited) == 0, _describe_members<T>, describe_inherited_members, T, mp11::mp_list<>>;
  95. // member_filter
  96. template<unsigned M> struct member_filter
  97. {
  98. template<class T> using fn = mp11::mp_bool<
  99. (M & mod_any_access & T::modifiers) != 0 &&
  100. ( (M & mod_any_member) != 0 || (M & mod_static) == (T::modifiers & mod_static) ) &&
  101. ( (M & mod_any_member) != 0 || (M & mod_function) == (T::modifiers & mod_function) ) &&
  102. (M & mod_hidden) >= (T::modifiers & mod_hidden)
  103. >;
  104. };
  105. // has_describe_members
  106. template<class T, class En = void> struct has_describe_members: std::false_type
  107. {
  108. };
  109. template<class T> struct has_describe_members<T, void_t<_describe_members<T>>>: std::true_type
  110. {
  111. };
  112. } // namespace detail
  113. template<class T, unsigned M> using describe_members = mp11::mp_copy_if_q<detail::describe_members<T, M>, detail::member_filter<M>>;
  114. template<class T> using has_describe_members = detail::has_describe_members<T>;
  115. } // namespace describe
  116. } // namespace boost
  117. #endif // !defined(BOOST_DESCRIBE_CXX11)
  118. #endif // #ifndef BOOST_DESCRIBE_DATA_MEMBERS_HPP_INCLUDED