Imported Upstream version 1.57.0
[platform/upstream/boost.git] / libs / optional / test / optional_test_value_access.cpp
1 // Copyright (C) 2014 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 // Revisions:
13 //
14 #include<iostream>
15 #include<stdexcept>
16 #include<string>
17
18 #define BOOST_ENABLE_ASSERT_HANDLER
19
20 #include "boost/bind/apply.hpp" // Included just to test proper interaction with boost::apply<> as reported by Daniel Wallin
21 #include "boost/mpl/bool.hpp"
22 #include "boost/mpl/bool_fwd.hpp"  // For mpl::true_ and mpl::false_
23
24 #include "boost/optional/optional.hpp"
25
26 #ifdef __BORLANDC__
27 #pragma hdrstop
28 #endif
29
30 #include "boost/none.hpp"
31
32 #include "boost/test/minimal.hpp"
33
34 #include "optional_test_common.cpp"
35
36 struct IntWrapper
37 {
38   int _i;
39   IntWrapper(int i) : _i(i) {}
40   bool operator==(IntWrapper const& rhs) const { return _i == rhs._i; }
41 };
42
43 template <typename T>
44 void test_function_value_or_for()
45 {
46   optional<T> oM0;
47   const optional<T> oC0;
48   optional<T> oM1(1);
49   const optional<T> oC2(2);
50   
51   BOOST_CHECK(oM0.value_or(5) == 5);
52   BOOST_CHECK(oC0.value_or(5) == 5);
53   BOOST_CHECK(oM1.value_or(5) == 1);
54   BOOST_CHECK(oC2.value_or(5) == 2);
55 }
56
57 template <typename T>
58 void test_function_value_for()
59 {
60   optional<T> o0;
61   optional<T> o1(1);
62   const optional<T> oC(2);
63   
64   try
65   {
66     T& v = o1.value();
67     BOOST_CHECK(v == 1);
68   }
69   catch(...)
70   {
71     BOOST_CHECK(false);
72   }
73   
74   try
75   {
76     T const& v = oC.value();
77     BOOST_CHECK(v == 2);
78   }
79   catch(...)
80   {
81     BOOST_CHECK(false);
82   }
83   
84   try
85   {
86     T& v = o0.value();
87     BOOST_CHECK(false);
88     boost::ignore_unused(v);
89   }
90   catch(boost::bad_optional_access const&)
91   {
92   }
93   catch(...)
94   {
95     BOOST_CHECK(false);
96   }
97 }
98
99 void test_function_value()
100 {
101     test_function_value_for<int>();
102     test_function_value_for<double>();
103     test_function_value_for<IntWrapper>();
104 }
105
106 struct FatToIntConverter
107 {
108   static int conversions;
109   int _val;
110   FatToIntConverter(int val) : _val(val) {}
111   operator int() const { conversions += 1; return _val; }
112 };
113
114 int FatToIntConverter::conversions = 0;
115
116 void test_function_value_or()
117 {
118     test_function_value_or_for<int>();
119     test_function_value_or_for<double>();
120     test_function_value_or_for<IntWrapper>();
121     
122     optional<int> oi(1);
123     BOOST_CHECK(oi.value_or(FatToIntConverter(2)) == 1);
124     BOOST_CHECK(FatToIntConverter::conversions == 0);
125     
126     oi = boost::none;
127     BOOST_CHECK(oi.value_or(FatToIntConverter(2)) == 2);
128     BOOST_CHECK(FatToIntConverter::conversions == 1);
129 }
130
131
132 struct FunM
133 {
134     int operator()() { return 5; }
135 };
136
137 struct FunC
138 {
139     int operator()() const { return 6; }
140 };
141
142 int funP ()
143 {
144     return 7;
145 }
146
147 int throw_()
148 {
149     throw int();
150 }
151
152 void test_function_value_or_eval()
153 {
154     optional<int> o1 = 1;
155     optional<int> oN;
156     FunM funM;
157     FunC funC;
158     
159     BOOST_CHECK(o1.value_or_eval(funM) == 1);
160     BOOST_CHECK(oN.value_or_eval(funM) == 5);
161     BOOST_CHECK(o1.value_or_eval(FunM()) == 1);
162     BOOST_CHECK(oN.value_or_eval(FunM()) == 5);
163     
164     BOOST_CHECK(o1.value_or_eval(funC) == 1);
165     BOOST_CHECK(oN.value_or_eval(funC) == 6);
166     BOOST_CHECK(o1.value_or_eval(FunC()) == 1);
167     BOOST_CHECK(oN.value_or_eval(FunC()) == 6);
168     
169     BOOST_CHECK(o1.value_or_eval(funP) == 1);
170     BOOST_CHECK(oN.value_or_eval(funP) == 7);
171     
172 #ifndef BOOST_NO_CXX11_LAMBDAS
173     BOOST_CHECK(o1.value_or_eval([](){return 8;}) == 1);
174     BOOST_CHECK(oN.value_or_eval([](){return 8;}) == 8);
175 #endif
176
177     try
178     {
179       BOOST_CHECK(o1.value_or_eval(throw_) == 1);
180     }
181     catch(...)
182     {
183       BOOST_CHECK(false);
184     }
185     
186     try
187     {
188       BOOST_CHECK(oN.value_or_eval(throw_) == 1);
189       BOOST_CHECK(false);
190     }
191     catch(...)
192     {
193       BOOST_CHECK(true);
194     }
195 }
196
197 const optional<std::string> makeConstOptVal()
198 {
199     return std::string("something");
200 }
201
202 void test_const_move()
203 {
204     std::string s5 = *makeConstOptVal();
205     std::string s6 = makeConstOptVal().value();
206     boost::ignore_unused(s5);
207     boost::ignore_unused(s6);
208 }
209
210
211 #ifndef BOOST_NO_CXX11_REF_QUALIFIERS
212 struct MoveOnly
213 {
214     explicit MoveOnly(int){}
215     MoveOnly(MoveOnly &&){}
216     void operator=(MoveOnly &&);
217 private:
218     MoveOnly(MoveOnly const&);
219     void operator=(MoveOnly const&);
220 };
221
222 optional<MoveOnly> makeMoveOnly()
223 {
224     return MoveOnly(1);
225 }
226
227 MoveOnly moveOnlyDefault()
228 {
229     return MoveOnly(1);
230 }
231
232 // compile-time test
233 void test_move_only_getters()
234 {
235     MoveOnly m1 = *makeMoveOnly();
236     MoveOnly m2 = makeMoveOnly().value();
237     MoveOnly m3 = makeMoveOnly().value_or(MoveOnly(1));
238     MoveOnly m4 = makeMoveOnly().value_or_eval(moveOnlyDefault);
239     boost::ignore_unused(m1);
240     boost::ignore_unused(m2);
241     boost::ignore_unused(m3);
242     boost::ignore_unused(m4);
243 }
244
245 #endif // !defined BOOST_NO_CXX11_REF_QUALIFIERS
246
247 int test_main( int, char* [] )
248 {
249   try
250   {
251     test_function_value();
252     test_function_value_or();
253     test_function_value_or_eval();
254     test_const_move();
255   }
256   catch ( ... )
257   {
258     BOOST_ERROR("Unexpected Exception caught!");
259   }
260
261   return 0;
262 }
263
264