1// Copyright (c) 2023 Bela Schaum, X-Ryl669, Denis Mikhailov.
2//
3// Distributed under the Boost Software License, Version 1.0. (See accompanying
4// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6
7// Initial implementation by Bela Schaum, https://github.com/schaumb
8// The way to make it union and UB free by X-Ryl669, https://github.com/X-Ryl669
9//
10
11#include <boost/pfr/core_name.hpp>
12
13#include <boost/core/lightweight_test.hpp>
14#include <functional> // for std::reference_wrapper
15#include <string>
16
17namespace testing {
18
19struct nonconstexpr {
20 nonconstexpr() {};
21};
22
23struct Aggregate {
24 int member1;
25 nonconstexpr this_is_a_name;
26 std::reference_wrapper<char> c;
27 std::string Forth;
28};
29
30struct A {
31 int first;
32 int second;
33};
34
35struct empty {};
36
37namespace {
38 struct inside_unnamed_ns {
39 int hidden;
40 };
41}
42
43struct {
44 int unnamed_first;
45 float unnamed_second;
46} unnamed{};
47
48typedef typename std::remove_reference<decltype(unnamed)>::type unnamed_t;
49
50void test_get_name_by_id() {
51 BOOST_TEST_EQ( ((boost::pfr::get_name<0, Aggregate>())), "member1");
52 BOOST_TEST_EQ( ((boost::pfr::get_name<1, Aggregate>())), "this_is_a_name");
53 BOOST_TEST_EQ( ((boost::pfr::get_name<2, Aggregate>())), "c");
54 BOOST_TEST_EQ( ((boost::pfr::get_name<3, Aggregate>())), "Forth");
55
56 BOOST_TEST_EQ( ((boost::pfr::get_name<0, A>())), "first");
57 BOOST_TEST_EQ( ((boost::pfr::get_name<1, A>())), "second");
58}
59
60void test_get_name_by_id_without_linkage() {
61// Disabling for MSVC as it gives a hard error on using local types:
62///
63// error C7631:
64// 'boost::pfr::detail::do_not_use_PFR_with_local_types<testing::unnamed_t>':
65// variable with internal linkage declared but not defined
66#ifndef _MSC_VER
67 struct function_local {
68 int val;
69 };
70
71 BOOST_TEST_EQ( ((boost::pfr::get_name<0, unnamed_t>())), "unnamed_first");
72 BOOST_TEST_EQ( ((boost::pfr::get_name<1, unnamed_t>())), "unnamed_second");
73
74 BOOST_TEST_EQ( ((boost::pfr::get_name<0, inside_unnamed_ns>())), "hidden");
75
76 BOOST_TEST_EQ( ((boost::pfr::get_name<0, function_local>())), "val");
77#endif
78}
79
80void test_get_name_by_type() {
81// FIXME: implement this
82// using char_ref = std::reference_wrapper<char>;
83// BOOST_TEST_EQ( ((boost::pfr::get_name<int, Aggregate>())), "member1");
84// BOOST_TEST_EQ( ((boost::pfr::get_name<nonconstexpr, Aggregate>())), "this_is_a_name");
85// BOOST_TEST_EQ( ((boost::pfr::get_name<char_ref, Aggregate>())), "c");
86}
87
88void test_get_name_by_type_without_linkage() {
89// FIXME: implement this
90// BOOST_TEST_EQ( ((boost::pfr::get_name<int, unnamed_t>())), "unnamed_first");
91// BOOST_TEST_EQ( ((boost::pfr::get_name<float, unnamed_t>())), "unnamed_second");
92// BOOST_TEST_EQ( ((boost::pfr::get_name<int, inside_unnamed_ns>())), "hidden");
93}
94
95void test_names_as_array() {
96 const auto expected = std::array<std::string_view, 4>{
97 "member1",
98 "this_is_a_name",
99 "c",
100 "Forth"
101 };
102 const auto value = boost::pfr::names_as_array<Aggregate>();
103 BOOST_TEST_EQ(expected.size(), value.size());
104 for (std::size_t i=0;i<expected.size();++i) {
105 BOOST_TEST_EQ(value[i], expected[i]);
106 }
107}
108
109void test_names_as_array_without_linkage() {
110// Disabling for MSVC as it gives a hard error on using local types:
111///
112// error C7631:
113// 'boost::pfr::detail::do_not_use_PFR_with_local_types<testing::unnamed_t>':
114// variable with internal linkage declared but not defined
115#ifndef _MSC_VER
116 const auto expected = std::array<std::string_view, 2>{
117 "unnamed_first",
118 "unnamed_second"
119 };
120 const auto value = boost::pfr::names_as_array<unnamed_t>();
121 BOOST_TEST_EQ(expected.size(), value.size());
122 for (std::size_t i=0;i<expected.size();++i) {
123 BOOST_TEST_EQ(value[i], expected[i]);
124 }
125#endif
126}
127
128void test_names_as_array_for_empty() {
129 const auto value = boost::pfr::names_as_array<empty>();
130 BOOST_TEST_EQ(value.size(), 0);
131 BOOST_TEST_EQ(value.empty(), true);
132}
133
134} // namespace testing
135
136int main() {
137 testing::test_get_name_by_id();
138 testing::test_get_name_by_id_without_linkage();
139 testing::test_get_name_by_type();
140 testing::test_get_name_by_type_without_linkage();
141 testing::test_names_as_array();
142 testing::test_names_as_array_without_linkage();
143 testing::test_names_as_array_for_empty();
144
145 return boost::report_errors();
146}
147
148
149

source code of boost/libs/pfr/test/core_name/run/fields_names.cpp