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