// // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_MYSQL_IMPL_PFR_HPP #define BOOST_MYSQL_IMPL_PFR_HPP #pragma once #include <boost/config.hpp> // Silence PFR warnings caused by https://github.com/boostorg/pfr/issues/166 // Only affecting gcc-11+, and caused during the inclusion of the library #if BOOST_GCC >= 110000 #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wpragmas" #endif // Silence MSVC 14.1 warnings caused by https://github.com/boostorg/pfr/issues/167 #if defined(BOOST_MSVC) && BOOST_MSVC < 1920 #pragma warning(push) #pragma warning(disable : 4100) #endif #include <boost/mysql/pfr.hpp> #include <boost/mysql/string_view.hpp> #include <boost/mysql/detail/typing/row_traits.hpp> #include <boost/pfr/core.hpp> #include <boost/pfr/core_name.hpp> #include <boost/pfr/traits.hpp> #include <type_traits> #include <utility> #if BOOST_PFR_CORE_NAME_ENABLED #include <array> #include <cstddef> #include <string_view> #endif #if BOOST_GCC >= 110000 #pragma GCC diagnostic pop #endif namespace boost { namespace mysql { namespace detail { // Not all types reflected by PFR are acceptable for us - this function performs this checking template <class T> constexpr bool is_pfr_reflectable() noexcept { return std::is_class<T>::value && !std::is_const<T>::value // is_implicitly_reflectable_v returns always false when implicit reflection // (which requires structured bindings and C++17) is not available #if BOOST_PFR_ENABLE_IMPLICIT_REFLECTION && pfr::is_implicitly_reflectable_v<T, struct mysql_tag> #endif ; } template <class T> using pfr_fields_t = decltype(pfr::structure_to_tuple(std::declval<const T&>())); #if BOOST_PFR_CORE_NAME_ENABLED // PFR field names use std::string_view template <std::size_t N> constexpr std::array<string_view, N> to_name_table_storage(std::array<std::string_view, N> input) noexcept { std::array<string_view, N> res; for (std::size_t i = 0; i < N; ++i) res[i] = input[i]; return res; } // Workaround for https://github.com/boostorg/pfr/issues/165 constexpr std::array<string_view, 0u> to_name_table_storage(std::array<std::nullptr_t, 0u>) noexcept { return {}; } template <class T> constexpr inline auto pfr_names_storage = to_name_table_storage(pfr::names_as_array<T>()); template <class T> class row_traits<pfr_by_name<T>, false> { static_assert( is_pfr_reflectable<T>(), "T needs to be a non-const object type that supports PFR reflection" ); public: using underlying_row_type = T; using field_types = pfr_fields_t<T>; static constexpr name_table_t name_table() noexcept { return pfr_names_storage<T>; } template <class F> static void for_each_member(T& to, F&& function) { pfr::for_each_field(to, std::forward<F>(function)); } }; #endif template <class T> class row_traits<pfr_by_position<T>, false> { static_assert( is_pfr_reflectable<T>(), "T needs to be a non-const object type that supports PFR reflection" ); public: using underlying_row_type = T; using field_types = pfr_fields_t<T>; static constexpr name_table_t name_table() noexcept { return {}; } template <class F> static void for_each_member(T& to, F&& function) { pfr::for_each_field(to, std::forward<F>(function)); } }; } // namespace detail } // namespace mysql } // namespace boost #if defined(BOOST_MSVC) && BOOST_MSVC < 1920 #pragma warning(pop) #endif #endif