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