1 // Copyright (C) 2018 Andrzej Krzemienski.
2 //
3 // Use, modification, and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // See http://www.boost.org/lib/optional for documentation.
8 //
9 // You are welcome to contact the author at:
10 // akrzemi1@gmail.com
11
12 #include "boost/optional/optional.hpp"
13
14 #ifdef BOOST_BORLANDC
15 #pragma hdrstop
16 #endif
17
18 #include "boost/core/ignore_unused.hpp"
19 #include "boost/core/is_same.hpp"
20 #include "boost/core/lightweight_test.hpp"
21 #include "boost/core/lightweight_test_trait.hpp"
22
23
24 using boost::optional;
25 using boost::make_optional;
26 using boost::core::is_same;
27
28 template <typename Expected, typename Deduced>
verify_type(Deduced)29 void verify_type(Deduced)
30 {
31 BOOST_TEST_TRAIT_TRUE(( is_same<Expected, Deduced> ));
32 }
33
34 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
35 struct MoveOnly
36 {
37 int value;
MoveOnlyMoveOnly38 explicit MoveOnly(int i) : value(i) {}
MoveOnlyMoveOnly39 MoveOnly(MoveOnly && r) : value(r.value) { r.value = 0; }
operator =MoveOnly40 MoveOnly& operator=(MoveOnly && r) { value = r.value; r.value = 0; return *this; }
41
42 private:
43 MoveOnly(MoveOnly const&);
44 void operator=(MoveOnly const&);
45 };
46
makeMoveOnly(int i)47 MoveOnly makeMoveOnly(int i)
48 {
49 return MoveOnly(i);
50 }
51
makeOptMoveOnly(int i)52 optional<MoveOnly> makeOptMoveOnly(int i)
53 {
54 return optional<MoveOnly>(MoveOnly(i));
55 }
56
get_val(MoveOnly m)57 int get_val(MoveOnly m)
58 {
59 return m.value;
60 }
61
test_map_move_only()62 void test_map_move_only()
63 {
64 optional<MoveOnly> om (makeMoveOnly(7)), om2 (makeMoveOnly(8));
65 verify_type<optional<int> >(boost::move(om).map(get_val));
66 optional<int> oi = boost::move(om2).map(get_val);
67 BOOST_TEST(bool(oi));
68 BOOST_TEST_EQ(8, *oi);
69
70 optional<int> oj = makeOptMoveOnly(4).map(get_val);
71 BOOST_TEST(bool(oj));
72 BOOST_TEST_EQ(4, *oj);
73
74 optional<MoveOnly> o_;
75 optional<int> oi_ = boost::move(o_).map(get_val);
76 BOOST_TEST(!oi_);
77 }
78
79 #endif // no rvalue refs
80
81 struct Int
82 {
83 int i;
IntInt84 explicit Int(int i_) : i(i_) {}
85 };
86
87 struct convert_t
88 {
89 typedef Int result_type;
operator ()convert_t90 Int operator()(int i) { return Int(i); }
91 };
92
get_int_ref(Int & i)93 int& get_int_ref(Int& i)
94 {
95 return i.i;
96 }
97
98 struct get_ref
99 {
100 typedef int& result_type;
operator ()get_ref101 int& operator()(int& i) { return i; }
102 };
103
test_map()104 void test_map()
105 {
106 optional<int> oi (1);
107 verify_type<optional<Int> >(oi.map(convert_t()));
108 optional<Int> oI = oi.map(convert_t());
109 BOOST_TEST(bool(oI));
110 BOOST_TEST_EQ(1, oI->i);
111
112 optional<Int> o_ = optional<int>().map(convert_t());
113 BOOST_TEST(!o_);
114 }
115
make_opt_int(int i)116 optional<Int> make_opt_int(int i)
117 {
118 if (i != 0)
119 return Int(i);
120 else
121 return boost::none;
122 }
123
test_map_optional()124 void test_map_optional()
125 {
126 optional<int> o9 (9), o0 (0), o_;
127 verify_type<optional<optional<Int> > >(o9.map(make_opt_int));
128 optional<optional<Int> > oo9 = o9.map(make_opt_int);
129 BOOST_TEST(bool(oo9));
130 BOOST_TEST(bool(*oo9));
131 BOOST_TEST_EQ(9, (**oo9).i);
132
133 optional<optional<Int> > oo0 = o0.map(make_opt_int);
134 BOOST_TEST(bool(oo0));
135 BOOST_TEST(!*oo0);
136
137 optional<optional<Int> > oo_ = o_.map(make_opt_int);
138 BOOST_TEST(!oo_);
139 }
140
test_map_with_lambda()141 void test_map_with_lambda()
142 {
143 #if !defined BOOST_NO_CXX11_LAMBDAS && !defined BOOST_NO_CXX11_DECLTYPE_N3276
144 optional<int> oi (1), oj(2);
145 verify_type<optional<bool> >(oi.map([](int i){ return i == 1; }));
146 optional<bool> ob = oi.map([](int i){ return i == 1; });
147 optional<bool> oc = oj.map([](int i){ return i == 1; });
148 BOOST_TEST(bool(ob));
149 BOOST_TEST_EQ(true, *ob);
150 BOOST_TEST(bool(oc));
151 BOOST_TEST_EQ(false, *oc);
152 #endif // lambdas
153 }
154
test_map_to_ref()155 void test_map_to_ref()
156 {
157 optional<int> oi (2);
158 verify_type<optional<int&> >(oi.map(get_ref()));
159 optional<int&> ori = oi.map(get_ref());
160 BOOST_TEST(bool(ori));
161 *ori = 3;
162 BOOST_TEST(bool(oi));
163 BOOST_TEST_EQ(3, *oi);
164 BOOST_TEST_EQ(3, *ori);
165 }
166
test_map_optional_ref()167 void test_map_optional_ref()
168 {
169 Int I (5);
170 optional<Int&> ori (I);
171 verify_type<optional<int&> >(ori.map(get_int_ref));
172 optional<int&> orii = ori.map(get_int_ref);
173 BOOST_TEST(bool(orii));
174 BOOST_TEST_EQ(5, *orii);
175 *orii = 6;
176 BOOST_TEST_EQ(6, I.i);
177 }
178
main()179 int main()
180 {
181 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
182 test_map_move_only();
183 #endif
184 test_map_with_lambda();
185 test_map();
186 test_map_optional();
187 test_map_to_ref();
188 test_map_optional();
189 test_map_optional_ref();
190
191 return boost::report_errors();
192 }
193