• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2016-2021 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 
20 struct adl_hash {
21     template <class T>
operator ()adl_hash22     std::size_t operator()(const T& val) const {
23         using namespace boost;
24         return hash_value(val);
25     }
26 };
27 
28 struct comparable_struct {
29     int i; short s; bool bl; int a,b,c,d,e,f;
30 };
31 
BOOST_PFR_FUNCTIONS_FOR(comparable_struct)32 BOOST_PFR_FUNCTIONS_FOR(comparable_struct)
33 
34 template <typename Struct>
35 void 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 ( 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 
test_comparable_struct()63 void test_comparable_struct() {
64     test_some_comparable_struct<comparable_struct>();
65 }
66 
operator std::stringempty67 struct empty { operator std::string() { return "empty{}"; } };
BOOST_PFR_FUNCTIONS_FOR(empty)68 BOOST_PFR_FUNCTIONS_FOR(empty)
69 
70 void test_empty_struct() {
71     BOOST_TEST_EQ(empty{}, empty{});
72 }
73 
74 namespace foo {
75     struct testing { bool b1, b2; int i; };
76     BOOST_PFR_FUNCTIONS_FOR(testing);
77 }
78 
79 template <class Comparator>
test_with_contatiners()80 void 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 
test_implicit_conversions()95 void 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("");
101     ss << empty{};
102     BOOST_TEST_EQ(ss.str(), "{}"); // Breaks implicit conversion for types marked with BOOST_PFR_FUNCTIONS_FOR
103 }
104 
105 namespace {
106 
107 struct anonymous_comparable_struct {
108     int i; short s; bool bl; int a,b,c,d,e,f;
109 };
110 
111 BOOST_PFR_FUNCTIONS_FOR(anonymous_comparable_struct)
112 
113 
114 struct other_anonymous_struct {
115     anonymous_comparable_struct a,b;
116 };
117 
118 BOOST_PFR_FUNCTIONS_FOR(other_anonymous_struct)
119 
120 }
121 
122 namespace std {
123 template <>
124 struct hash<anonymous_comparable_struct> {
operator ()std::hash125     std::size_t operator()(const anonymous_comparable_struct& val) const noexcept {
126         return hash_value(val);
127     }
128 };
129 }
130 
131 namespace {
132 
test_anonymous_comparable_struct()133 void test_anonymous_comparable_struct() {
134     test_some_comparable_struct<anonymous_comparable_struct>();
135 }
136 
test_nested_anonymous_comparable_struct()137 void test_nested_anonymous_comparable_struct() {
138     other_anonymous_struct s1{
139         {0, 1, false, 6,7,8,9,10,11},
140         {0, 1, false, 6,7,8,9,10,11},
141     };
142     auto s2 = s1;
143 
144     BOOST_TEST_EQ(s1, s2);
145 }
146 
147 }
148 
main()149 int 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