• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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