pfr.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. //
  2. // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_IMPL_PFR_HPP
  8. #define BOOST_MYSQL_IMPL_PFR_HPP
  9. #pragma once
  10. #include <boost/config.hpp>
  11. // Silence PFR warnings caused by https://github.com/boostorg/pfr/issues/166
  12. // Only affecting gcc-11+, and caused during the inclusion of the library
  13. #if BOOST_GCC >= 110000
  14. #pragma GCC diagnostic push
  15. #pragma GCC diagnostic ignored "-Wpragmas"
  16. #endif
  17. // Silence MSVC 14.1 warnings caused by https://github.com/boostorg/pfr/issues/167
  18. #if defined(BOOST_MSVC) && BOOST_MSVC < 1920
  19. #pragma warning(push)
  20. #pragma warning(disable : 4100)
  21. #endif
  22. #include <boost/mysql/pfr.hpp>
  23. #include <boost/mysql/string_view.hpp>
  24. #include <boost/mysql/detail/typing/row_traits.hpp>
  25. #include <boost/pfr/core.hpp>
  26. #include <boost/pfr/core_name.hpp>
  27. #include <boost/pfr/traits.hpp>
  28. #include <type_traits>
  29. #include <utility>
  30. #if BOOST_PFR_CORE_NAME_ENABLED
  31. #include <array>
  32. #include <cstddef>
  33. #include <string_view>
  34. #endif
  35. #if BOOST_GCC >= 110000
  36. #pragma GCC diagnostic pop
  37. #endif
  38. namespace boost {
  39. namespace mysql {
  40. namespace detail {
  41. // Not all types reflected by PFR are acceptable for us - this function performs this checking
  42. template <class T>
  43. constexpr bool is_pfr_reflectable() noexcept
  44. {
  45. return std::is_class<T>::value && !std::is_const<T>::value
  46. // is_implicitly_reflectable_v returns always false when implicit reflection
  47. // (which requires structured bindings and C++17) is not available
  48. #if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION
  49. && pfr::is_implicitly_reflectable_v<T, struct mysql_tag>
  50. #endif
  51. ;
  52. }
  53. template <class T>
  54. using pfr_fields_t = decltype(pfr::structure_to_tuple(std::declval<const T&>()));
  55. #if BOOST_PFR_CORE_NAME_ENABLED
  56. // PFR field names use std::string_view
  57. template <std::size_t N>
  58. constexpr std::array<string_view, N> to_name_table_storage(std::array<std::string_view, N> input) noexcept
  59. {
  60. std::array<string_view, N> res;
  61. for (std::size_t i = 0; i < N; ++i)
  62. res[i] = input[i];
  63. return res;
  64. }
  65. // Workaround for https://github.com/boostorg/pfr/issues/165
  66. constexpr std::array<string_view, 0u> to_name_table_storage(std::array<std::nullptr_t, 0u>) noexcept
  67. {
  68. return {};
  69. }
  70. template <class T>
  71. constexpr inline auto pfr_names_storage = to_name_table_storage(pfr::names_as_array<T>());
  72. template <class T>
  73. class row_traits<pfr_by_name<T>, false>
  74. {
  75. static_assert(
  76. is_pfr_reflectable<T>(),
  77. "T needs to be a non-const object type that supports PFR reflection"
  78. );
  79. public:
  80. using underlying_row_type = T;
  81. using field_types = pfr_fields_t<T>;
  82. static constexpr name_table_t name_table() noexcept { return pfr_names_storage<T>; }
  83. template <class F>
  84. static void for_each_member(T& to, F&& function)
  85. {
  86. pfr::for_each_field(to, std::forward<F>(function));
  87. }
  88. };
  89. #endif
  90. template <class T>
  91. class row_traits<pfr_by_position<T>, false>
  92. {
  93. static_assert(
  94. is_pfr_reflectable<T>(),
  95. "T needs to be a non-const object type that supports PFR reflection"
  96. );
  97. public:
  98. using underlying_row_type = T;
  99. using field_types = pfr_fields_t<T>;
  100. static constexpr name_table_t name_table() noexcept { return {}; }
  101. template <class F>
  102. static void for_each_member(T& to, F&& function)
  103. {
  104. pfr::for_each_field(to, std::forward<F>(function));
  105. }
  106. };
  107. } // namespace detail
  108. } // namespace mysql
  109. } // namespace boost
  110. #if defined(BOOST_MSVC) && BOOST_MSVC < 1920
  111. #pragma warning(pop)
  112. #endif
  113. #endif