diff --git a/doc/pfr.qbk b/doc/pfr.qbk index b53638a..4745b4d 100644 --- a/doc/pfr.qbk +++ b/doc/pfr.qbk @@ -466,6 +466,7 @@ By default Boost.PFR [*auto-detects your compiler abilities] and automatically d [[*BOOST_PFR_USE_CPP17*] [Define to `1` if you wish to override Boost.PFR choice and use C++17 structured bindings for reflection. Define to `0` to override Boost.PFR choice and disable C++17 structured bindings usage.]] [[*BOOST_PFR_USE_LOOPHOLE*] [Define to `1` if you wish to override Boost.PFR choice and exploit [@http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2118 CWG 2118] for reflection. Define to `0` to override Boost.PFR choice and disable CWG 2118 usage.]] [[*BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE*] [Define to `0` if you are hit by the template instantiation depth issues with `std::make_integer_sequence` and wish to use Boost.PFR version of that metafunction. Define to `1` to override Boost.PFR detection logic. ]] + [[*BOOST_PFR_HAS_GUARANTEED_COPY_ELISION*] [Define to `0` if your compiler does not implement C++17 guaranteed copy elision properly and fails to reflect aggregates with non-movable fields. Define to `1` to override Boost.PFR detection logic. ]] ] diff --git a/include/boost/pfr/detail/config.hpp b/include/boost/pfr/detail/config.hpp index e8ffb0e..300f8d2 100644 --- a/include/boost/pfr/detail/config.hpp +++ b/include/boost/pfr/detail/config.hpp @@ -66,6 +66,14 @@ # endif #endif +#ifndef BOOST_PFR_HAS_GUARANTEED_COPY_ELISION +# if defined(__cpp_guaranteed_copy_elision) && (!defined(_MSC_VER) || _MSC_VER > 1928) +# define BOOST_PFR_HAS_GUARANTEED_COPY_ELISION 1 +# else +# define BOOST_PFR_HAS_GUARANTEED_COPY_ELISION 0 +# endif +#endif + #if defined(__has_cpp_attribute) # if __has_cpp_attribute(maybe_unused) # define BOOST_PFR_MAYBE_UNUSED [[maybe_unused]] diff --git a/include/boost/pfr/detail/fields_count.hpp b/include/boost/pfr/detail/fields_count.hpp index 7b2b79b..6b4483d 100644 --- a/include/boost/pfr/detail/fields_count.hpp +++ b/include/boost/pfr/detail/fields_count.hpp @@ -210,7 +210,7 @@ constexpr std::size_t fields_count() noexcept { "====================> Boost.PFR: Attempt to get fields count on a reference. This is not allowed because that could hide an issue and different library users expect different behavior in that case." ); -#ifndef __cpp_guaranteed_copy_elision +#if !BOOST_PFR_HAS_GUARANTEED_COPY_ELISION static_assert( std::is_copy_constructible>::value || ( std::is_move_constructible>::value @@ -218,7 +218,7 @@ constexpr std::size_t fields_count() noexcept { ), "====================> Boost.PFR: Type and each field in the type must be copy constructible (or move constructible and move assignable)." ); -#endif // #ifndef __cpp_guaranteed_copy_elision +#endif // #if !BOOST_PFR_HAS_GUARANTEED_COPY_ELISION static_assert( !std::is_polymorphic::value, diff --git a/test/print_config.cpp b/test/print_config.cpp index e0123a0..4f9c049 100644 --- a/test/print_config.cpp +++ b/test/print_config.cpp @@ -12,6 +12,7 @@ int main() { << "BOOST_PFR_USE_CPP17 == " << BOOST_PFR_USE_CPP17 << '\n' << "BOOST_PFR_USE_LOOPHOLE == " << BOOST_PFR_USE_LOOPHOLE << '\n' << "BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE == " << BOOST_PFR_USE_STD_MAKE_INTEGRAL_SEQUENCE << '\n' + << "BOOST_PFR_HAS_GUARANTEED_COPY_ELISION == " << BOOST_PFR_HAS_GUARANTEED_COPY_ELISION << '\n' << "__cplusplus == " << __cplusplus << '\n' #ifdef __cpp_structured_bindings << "__cpp_structured_bindings == " << __cpp_structured_bindings << '\n' diff --git a/test/run/non_movable.cpp b/test/run/non_movable.cpp index 90b7f4a..d9fc8c3 100644 --- a/test/run/non_movable.cpp +++ b/test/run/non_movable.cpp @@ -18,7 +18,7 @@ struct X { struct S { X x0; X x1; int x2; X x3; }; int main() { -#ifdef __cpp_guaranteed_copy_elision +#if BOOST_PFR_HAS_GUARANTEED_COPY_ELISION static_assert(boost::pfr::tuple_size_v == 4, ""); struct S5_0 { int x0; int x1; int x2; int x3; X x4; }; @@ -38,7 +38,7 @@ int main() { struct S6 { X x0; X x1; X x2; X x3; X x4; X x5;}; static_assert(boost::pfr::tuple_size_v == 6, ""); -#endif // #ifdef __cpp_guaranteed_copy_elision +#endif // #if BOOST_PFR_HAS_GUARANTEED_COPY_ELISION return boost::report_errors(); }