// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov. // // 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) // Initial implementation by Bela Schaum, https://github.com/schaumb // The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669 // #include #include #include // for std::reference_wrapper #include namespace testing { struct nonconstexpr { nonconstexpr() {}; }; struct Aggregate { int member1; nonconstexpr this_is_a_name; std::reference_wrapper c; std::string Forth; }; struct A { int first; int second; }; struct empty {}; namespace { struct inside_unnamed_ns { int hidden; }; } struct { int unnamed_first; float unnamed_second; } unnamed{}; typedef typename std::remove_reference::type unnamed_t; void test_get_name_by_id() { BOOST_TEST_EQ( ((boost::pfr::get_name<0, Aggregate>())), "member1"); BOOST_TEST_EQ( ((boost::pfr::get_name<1, Aggregate>())), "this_is_a_name"); BOOST_TEST_EQ( ((boost::pfr::get_name<2, Aggregate>())), "c"); BOOST_TEST_EQ( ((boost::pfr::get_name<3, Aggregate>())), "Forth"); BOOST_TEST_EQ( ((boost::pfr::get_name<0, A>())), "first"); BOOST_TEST_EQ( ((boost::pfr::get_name<1, A>())), "second"); } void test_get_name_by_id_without_linkage() { // Disabling for MSVC as it gives a hard error on using local types: /// // error C7631: // 'boost::pfr::detail::do_not_use_PFR_with_local_types': // variable with internal linkage declared but not defined #ifndef _MSC_VER struct function_local { int val; }; BOOST_TEST_EQ( ((boost::pfr::get_name<0, unnamed_t>())), "unnamed_first"); BOOST_TEST_EQ( ((boost::pfr::get_name<1, unnamed_t>())), "unnamed_second"); BOOST_TEST_EQ( ((boost::pfr::get_name<0, inside_unnamed_ns>())), "hidden"); BOOST_TEST_EQ( ((boost::pfr::get_name<0, function_local>())), "val"); #endif } void test_get_name_by_type() { // FIXME: implement this // using char_ref = std::reference_wrapper; // BOOST_TEST_EQ( ((boost::pfr::get_name())), "member1"); // BOOST_TEST_EQ( ((boost::pfr::get_name())), "this_is_a_name"); // BOOST_TEST_EQ( ((boost::pfr::get_name())), "c"); } void test_get_name_by_type_without_linkage() { // FIXME: implement this // BOOST_TEST_EQ( ((boost::pfr::get_name())), "unnamed_first"); // BOOST_TEST_EQ( ((boost::pfr::get_name())), "unnamed_second"); // BOOST_TEST_EQ( ((boost::pfr::get_name())), "hidden"); } void test_names_as_array() { const auto expected = std::array{ "member1", "this_is_a_name", "c", "Forth" }; const auto value = boost::pfr::names_as_array(); BOOST_TEST_EQ(expected.size(), value.size()); for (std::size_t i=0;i': // variable with internal linkage declared but not defined #ifndef _MSC_VER const auto expected = std::array{ "unnamed_first", "unnamed_second" }; const auto value = boost::pfr::names_as_array(); BOOST_TEST_EQ(expected.size(), value.size()); for (std::size_t i=0;i(); BOOST_TEST_EQ(value.size(), 0); BOOST_TEST_EQ(value.empty(), true); } void test_names_as_array_iteration_for_empty() { const auto names = boost::pfr::names_as_array(); for (std::string_view name : names) { BOOST_ERROR("`names` must be empty"); } } } // namespace testing int main() { testing::test_get_name_by_id(); testing::test_get_name_by_id_without_linkage(); testing::test_get_name_by_type(); testing::test_get_name_by_type_without_linkage(); testing::test_names_as_array(); testing::test_names_as_array_without_linkage(); testing::test_names_as_array_for_empty(); testing::test_names_as_array_iteration_for_empty(); return boost::report_errors(); }