1// Copyright (c) 2016-2024 Antony Polukhin
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#include <boost/pfr/functions_for.hpp>
7
8#include <boost/core/lightweight_test.hpp>
9
10#include <iostream>
11#include <typeinfo>
12#include <tuple>
13#include <sstream>
14#include <set>
15#include <string>
16
17#include <boost/functional/hash.hpp>
18#include <unordered_set>
19
20struct adl_hash {
21 template <class T>
22 std::size_t operator()(const T& val) const {
23 using namespace boost;
24 return hash_value(val);
25 }
26};
27
28struct comparable_struct {
29 int i; short s; bool bl; int a,b,c,d,e,f;
30};
31
32BOOST_PFR_FUNCTIONS_FOR(comparable_struct)
33
34template <typename Struct>
35void test_some_comparable_struct() {
36 Struct s1 {0, 1, false, 6,7,8,9,10,11};
37 Struct s2 = s1;
38 Struct s3 {0, 1, false, 6,7,8,9,10,11111};
39 BOOST_TEST_EQ(s1, s2);
40 BOOST_TEST(s1 <= s2);
41 BOOST_TEST(s1 >= s2);
42 BOOST_TEST(!(s1 != s2));
43 BOOST_TEST(!(s1 == s3));
44 BOOST_TEST(s1 != s3);
45 BOOST_TEST(s1 < s3);
46 BOOST_TEST(s3 > s2);
47 BOOST_TEST(s1 <= s3);
48 BOOST_TEST(s3 >= s2);
49
50 std::cout << s1 << std::endl;
51
52 Struct s4;
53 std::stringstream ss;
54 ss.exceptions ( except: std::ios::failbit);
55 ss << s1;
56 ss >> s4;
57 std::cout << s4 << std::endl;
58 BOOST_TEST_EQ(s1, s4);
59 int i = 1, j = 2;
60 BOOST_TEST_NE(i, j);
61}
62
63void test_comparable_struct() {
64 test_some_comparable_struct<comparable_struct>();
65}
66
67struct empty { operator std::string() { return "empty{}"; } };
68BOOST_PFR_FUNCTIONS_FOR(empty)
69
70void test_empty_struct() {
71 BOOST_TEST_EQ(empty{}, empty{});
72}
73
74namespace foo {
75 struct testing { bool b1, b2; int i; };
76 BOOST_PFR_FUNCTIONS_FOR(testing)
77}
78
79template <class Comparator>
80void test_with_contatiners() {
81 std::set<foo::testing, Comparator > t{
82 {true, true, 100},
83 {false, true, 100},
84 {true, false, 100},
85 {true, true, 101}
86 };
87
88 BOOST_TEST(t.find({true, true, 100}) != t.end());
89 BOOST_TEST_EQ(t.count({true, true, 100}), 1u);
90
91 std::unordered_set<foo::testing, adl_hash> us(t.begin(), t.end());
92 BOOST_TEST_EQ(us.size(), t.size());
93}
94
95void test_implicit_conversions() {
96 std::stringstream ss;
97 ss << std::true_type{};
98 BOOST_TEST_EQ(ss.str(), "1"); // Does not breaks implicit conversion
99
100 ss.str(s: "");
101 ss << empty{};
102 BOOST_TEST_EQ(ss.str(), "{}"); // Breaks implicit conversion for types marked with BOOST_PFR_FUNCTIONS_FOR
103}
104
105namespace {
106
107struct anonymous_comparable_struct {
108 int i; short s; bool bl; int a,b,c,d,e,f;
109};
110
111BOOST_PFR_FUNCTIONS_FOR(anonymous_comparable_struct)
112
113
114struct other_anonymous_struct {
115 anonymous_comparable_struct a,b;
116};
117
118BOOST_PFR_FUNCTIONS_FOR(other_anonymous_struct)
119
120}
121
122namespace std {
123template <>
124struct hash<anonymous_comparable_struct> {
125 std::size_t operator()(const anonymous_comparable_struct& val) const noexcept {
126 return hash_value(v: val);
127 }
128};
129}
130
131namespace {
132
133void test_anonymous_comparable_struct() {
134 test_some_comparable_struct<anonymous_comparable_struct>();
135}
136
137void test_nested_anonymous_comparable_struct() {
138 other_anonymous_struct s1{
139 .a: {.i: 0, .s: 1, .bl: false, .a: 6,.b: 7,.c: 8,.d: 9,.e: 10,.f: 11},
140 .b: {.i: 0, .s: 1, .bl: false, .a: 6,.b: 7,.c: 8,.d: 9,.e: 10,.f: 11},
141 };
142 auto s2 = s1;
143
144 BOOST_TEST_EQ(s1, s2);
145}
146
147}
148
149int main() {
150 test_comparable_struct();
151 test_empty_struct();
152 test_with_contatiners<std::less<>>();
153 test_with_contatiners<std::greater<>>();
154 test_implicit_conversions();
155 test_anonymous_comparable_struct();
156 test_nested_anonymous_comparable_struct();
157 return boost::report_errors();
158}
159
160
161

source code of boost/libs/pfr/test/core/run/functions_for.cpp