From 638fefedd09256b928f05e2aaf11f0a941df4b22 Mon Sep 17 00:00:00 2001 From: Antony Polukhin Date: Wed, 24 Mar 2021 09:58:20 +0300 Subject: [PATCH] Allow reflection of aggregates with non movable fields if guaranteed copy elision is on --- include/boost/pfr/detail/fields_count.hpp | 6 ++- test/run/non_movable.cpp | 45 +++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 test/run/non_movable.cpp diff --git a/include/boost/pfr/detail/fields_count.hpp b/include/boost/pfr/detail/fields_count.hpp index 5c2bea3..7b2b79b 100644 --- a/include/boost/pfr/detail/fields_count.hpp +++ b/include/boost/pfr/detail/fields_count.hpp @@ -41,8 +41,8 @@ struct ubiq_lref_constructor { ///////////////////// Structure that can be converted to rvalue reference to anything struct ubiq_rref_constructor { std::size_t ignore; - template /*constexpr*/ operator Type&&() const && noexcept { // Allows initialization of rvalue reference fields and move-only types - return detail::unsafe_declval(); + template /*constexpr*/ operator Type() const && noexcept { // Allows initialization of rvalue reference fields and move-only types + return detail::unsafe_declval(); }; }; @@ -210,6 +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 static_assert( std::is_copy_constructible>::value || ( std::is_move_constructible>::value @@ -217,6 +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 static_assert( !std::is_polymorphic::value, diff --git a/test/run/non_movable.cpp b/test/run/non_movable.cpp new file mode 100644 index 0000000..90b7f4a --- /dev/null +++ b/test/run/non_movable.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2018-2021 Antony Polukhin +// +// 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) + +#include + +#include + +struct X { + X() = default; + X(X&&) = delete; + X(const X&) = delete; + + X& operator=(X&&) = delete; + X& operator=(const X&) = delete; +}; +struct S { X x0; X x1; int x2; X x3; }; + +int main() { +#ifdef __cpp_guaranteed_copy_elision + static_assert(boost::pfr::tuple_size_v == 4, ""); + + struct S5_0 { int x0; int x1; int x2; int x3; X x4; }; + static_assert(boost::pfr::tuple_size_v == 5, ""); + + struct S5_1 { X x0; int x1; int x2; int x3; int x4; }; + static_assert(boost::pfr::tuple_size_v == 5, ""); + + struct S5_2 { int x0; int x1; X x2; int x3; int x4; }; + static_assert(boost::pfr::tuple_size_v == 5, ""); + + struct S5_3 { int x0; int x1; X x2; int x3; X x4; }; + static_assert(boost::pfr::tuple_size_v == 5, ""); + + struct S5_4 { X x0; X x1; X x2; X x3; X x4; }; + static_assert(boost::pfr::tuple_size_v == 5, ""); + + 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 + + return boost::report_errors(); +} +