1 // Copyright (C) 2014 - 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 #define BOOST_OPTIONAL_CONFIG_USE_OLD_IMPLEMENTATION_OF_OPTIONAL // does old implementation still work for basic usage?
13 #include "boost/optional/optional.hpp"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #include "boost/core/ignore_unused.hpp"
20 #include "boost/core/lightweight_test.hpp"
21
22 using boost::optional;
23
24 struct IntWrapper
25 {
26 int _i;
IntWrapperIntWrapper27 IntWrapper(int i) : _i(i) {}
operator ==IntWrapper28 bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; }
29 };
30
31 template <typename T>
test_function_value_or_for()32 void test_function_value_or_for()
33 {
34 optional<T> oM0;
35 const optional<T> oC0;
36 optional<T> oM1(1);
37 const optional<T> oC2(2);
38
39 BOOST_TEST(oM0.value_or(5) == 5);
40 BOOST_TEST(oC0.value_or(5) == 5);
41 BOOST_TEST(oM1.value_or(5) == 1);
42 BOOST_TEST(oC2.value_or(5) == 2);
43 }
44
45 template <typename T>
test_function_value_for()46 void test_function_value_for()
47 {
48 optional<T> o0;
49 optional<T> o1(1);
50 const optional<T> oC(2);
51
52 try
53 {
54 T& v = o1.value();
55 BOOST_TEST(v == 1);
56 }
57 catch(...)
58 {
59 BOOST_TEST(false);
60 }
61
62 try
63 {
64 T const& v = oC.value();
65 BOOST_TEST(v == 2);
66 }
67 catch(...)
68 {
69 BOOST_TEST(false);
70 }
71
72 BOOST_TEST_THROWS(o0.value(), boost::bad_optional_access);
73 }
74
test_function_value()75 void test_function_value()
76 {
77 test_function_value_for<int>();
78 test_function_value_for<double>();
79 test_function_value_for<IntWrapper>();
80 }
81
82 struct FatToIntConverter
83 {
84 static int conversions;
85 int _val;
FatToIntConverterFatToIntConverter86 FatToIntConverter(int val) : _val(val) {}
operator intFatToIntConverter87 operator int() const { conversions += 1; return _val; }
88 };
89
90 int FatToIntConverter::conversions = 0;
91
test_function_value_or()92 void test_function_value_or()
93 {
94 test_function_value_or_for<int>();
95 test_function_value_or_for<double>();
96 test_function_value_or_for<IntWrapper>();
97
98 optional<int> oi(1);
99 BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 1);
100 BOOST_TEST(FatToIntConverter::conversions == 0);
101
102 oi = boost::none;
103 BOOST_TEST(oi.value_or(FatToIntConverter(2)) == 2);
104 BOOST_TEST(FatToIntConverter::conversions == 1);
105 }
106
107
108 struct FunM
109 {
operator ()FunM110 int operator()() { return 5; }
111 };
112
113 struct FunC
114 {
operator ()FunC115 int operator()() const { return 6; }
116 };
117
funP()118 int funP ()
119 {
120 return 7;
121 }
122
throw_()123 int throw_()
124 {
125 throw int();
126 }
127
test_function_value_or_eval()128 void test_function_value_or_eval()
129 {
130 optional<int> o1 = 1;
131 optional<int> oN;
132 FunM funM;
133 FunC funC;
134
135 BOOST_TEST_EQ(o1.value_or_eval(funM), 1);
136 BOOST_TEST_EQ(oN.value_or_eval(funM), 5);
137 BOOST_TEST_EQ(o1.value_or_eval(FunM()), 1);
138 BOOST_TEST_EQ(oN.value_or_eval(FunM()), 5);
139
140 BOOST_TEST_EQ(o1.value_or_eval(funC), 1);
141 BOOST_TEST_EQ(oN.value_or_eval(funC), 6);
142 BOOST_TEST_EQ(o1.value_or_eval(FunC()), 1);
143 BOOST_TEST_EQ(oN.value_or_eval(FunC()), 6);
144
145 BOOST_TEST_EQ(o1.value_or_eval(funP), 1);
146 BOOST_TEST_EQ(oN.value_or_eval(funP), 7);
147
148 #ifndef BOOST_NO_CXX11_LAMBDAS
149 BOOST_TEST_EQ(o1.value_or_eval([](){return 8;}), 1);
150 BOOST_TEST_EQ(oN.value_or_eval([](){return 8;}), 8);
151 #endif
152
153 try
154 {
155 BOOST_TEST_EQ(o1.value_or_eval(throw_), 1);
156 }
157 catch(...)
158 {
159 BOOST_TEST(false);
160 }
161
162 BOOST_TEST_THROWS(oN.value_or_eval(throw_), int);
163 }
164
makeConstOptVal()165 const optional<std::string> makeConstOptVal()
166 {
167 return std::string("something");
168 }
169
test_const_move()170 void test_const_move()
171 {
172 std::string s5 = *makeConstOptVal();
173 std::string s6 = makeConstOptVal().value();
174 boost::ignore_unused(s5);
175 boost::ignore_unused(s6);
176 }
177
178
179 #if (!defined BOOST_NO_CXX11_REF_QUALIFIERS) && (!defined BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES)
180 struct MoveOnly
181 {
MoveOnlyMoveOnly182 explicit MoveOnly(int){}
MoveOnlyMoveOnly183 MoveOnly(MoveOnly &&){}
184 void operator=(MoveOnly &&);
185 private:
186 MoveOnly(MoveOnly const&);
187 void operator=(MoveOnly const&);
188 };
189
makeMoveOnly()190 optional<MoveOnly> makeMoveOnly()
191 {
192 return MoveOnly(1);
193 }
194
moveOnlyDefault()195 MoveOnly moveOnlyDefault()
196 {
197 return MoveOnly(1);
198 }
199
200 // compile-time test
test_move_only_getters()201 void test_move_only_getters()
202 {
203 MoveOnly m1 = *makeMoveOnly();
204 MoveOnly m2 = makeMoveOnly().value();
205 MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1));
206 MoveOnly m4 = makeMoveOnly().value_or_eval(moveOnlyDefault);
207 boost::ignore_unused(m1);
208 boost::ignore_unused(m2);
209 boost::ignore_unused(m3);
210 boost::ignore_unused(m4);
211 }
212
213 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
214
main()215 int main()
216 {
217 test_function_value();
218 test_function_value_or();
219 test_function_value_or_eval();
220 test_const_move();
221
222 return boost::report_errors();
223 }
224