diff --git a/example/quick_examples.cpp b/example/quick_examples.cpp index 0208cf1..00e065b 100644 --- a/example/quick_examples.cpp +++ b/example/quick_examples.cpp @@ -106,7 +106,7 @@ void test_examples() { //] } -#if BOOST_PFR_CORE_NAME_ENABLED +#if BOOST_PFR_CORE_NAME_ENABLED && BOOST_PFR_USE_CPP17 { //[pfr_quick_examples_get_name // Get name of field by index diff --git a/include/boost/pfr/core.hpp b/include/boost/pfr/core.hpp index 49bdec5..5a8e1df 100644 --- a/include/boost/pfr/core.hpp +++ b/include/boost/pfr/core.hpp @@ -140,7 +140,7 @@ using tuple_element_t = typename tuple_element::type; /// assert(get<0>(t) == 10); /// \endcode template -constexpr auto structure_to_tuple(const T& val) noexcept { +constexpr auto structure_to_tuple(const T& val) { return detail::make_stdtuple_from_tietuple( detail::tie_as_tuple(val), detail::make_index_sequence< tuple_size_v >() diff --git a/include/boost/pfr/detail/fake_object.hpp b/include/boost/pfr/detail/fake_object.hpp index 54e0f75..271ac19 100644 --- a/include/boost/pfr/detail/fake_object.hpp +++ b/include/boost/pfr/detail/fake_object.hpp @@ -14,6 +14,15 @@ #include +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wundefined-internal" +# pragma clang diagnostic ignored "-Wundefined-var-template" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wundefined-var-template" +#endif + namespace boost { namespace pfr { namespace detail { // This class has external linkage while T has not sure. @@ -39,5 +48,10 @@ constexpr const T& fake_object() noexcept { }}} // namespace boost::pfr::detail +#ifdef __clang__ +# pragma clang diagnostic push +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif #endif // BOOST_PFR_DETAIL_FAKE_OBJECT_HPP diff --git a/include/boost/pfr/detail/stdtuple.hpp b/include/boost/pfr/detail/stdtuple.hpp index cf88e11..4359e34 100644 --- a/include/boost/pfr/detail/stdtuple.hpp +++ b/include/boost/pfr/detail/stdtuple.hpp @@ -17,7 +17,7 @@ namespace boost { namespace pfr { namespace detail { template -constexpr auto make_stdtuple_from_tietuple(const T& t, std::index_sequence) noexcept { +constexpr auto make_stdtuple_from_tietuple(const T& t, std::index_sequence) { return std::make_tuple( boost::pfr::detail::sequence_tuple::get(t)... ); diff --git a/test/core/run/structure_to_tuple.cpp b/test/core/run/structure_to_tuple.cpp new file mode 100644 index 0000000..a07384d --- /dev/null +++ b/test/core/run/structure_to_tuple.cpp @@ -0,0 +1,91 @@ +// Copyright (c) 2020-2024 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 + +namespace some { + struct struct1{ int i; }; + struct struct2{ int i; short s; }; +} + + +void test_single_field() { + { + some::struct1 s{1}; + auto s_tuple = boost::pfr::structure_to_tuple(s); + BOOST_TEST_EQ(std::get<0>(s_tuple), 1); + + static_assert(std::is_same< + std::tuple, decltype(s_tuple) + >::value, ""); + } + { + const some::struct1 s{1}; + auto s_tuple = boost::pfr::structure_to_tuple(s); + BOOST_TEST_EQ(std::get<0>(s_tuple), 1); + + static_assert(std::is_same< + std::tuple, decltype(s_tuple) + >::value, ""); + } +} + + +void test_two_fields() { + { + some::struct2 s{1, 2}; + auto s_tuple = boost::pfr::structure_to_tuple(s); + BOOST_TEST_EQ(std::get<0>(s_tuple), 1); + BOOST_TEST_EQ(std::get<1>(s_tuple), 2); + + static_assert(std::is_same< + std::tuple, decltype(s_tuple) + >::value, ""); + } + { + const some::struct2 s{1, 2}; + auto s_tuple = boost::pfr::structure_to_tuple(s); + BOOST_TEST_EQ(std::get<0>(s_tuple), 1); + BOOST_TEST_EQ(std::get<1>(s_tuple), 2); + + static_assert(std::is_same< + std::tuple, decltype(s_tuple) + >::value, ""); + } +} + +// Test from https://github.com/boostorg/pfr/issues/155 +void test_throwing_field() { +#if BOOST_PFR_USE_CPP17 || BOOST_PFR_USE_LOOPHOLE + struct throw_on_copy { + throw_on_copy() = default; + throw_on_copy(const throw_on_copy&){ throw 42; } + }; + + struct throwing_struct { + int i; + throw_on_copy s; + }; + + throwing_struct s {10, {}}; + try { + std::tuple t = boost::pfr::structure_to_tuple(s); + BOOST_TEST(false); // the above line should throw + (void)t; + } catch (...) {} +#endif +} + +int main() { + test_single_field(); + test_two_fields(); + test_throwing_field(); + + return boost::report_errors(); +} + +