Imported Upstream version 1.72.0
[platform/upstream/boost.git] / libs / outcome / doc / src / snippets / using_result.cpp
1 /* Documentation snippet
2 (C) 2017-2019 Niall Douglas <http://www.nedproductions.biz/> (7 commits), Andrzej Krzemienski <akrzemi1@gmail.com> (4 commits) and Krzemienski <sg0897542@global.ad.sabre.com> (2 commits)
3 File Created: Mar 2017
4
5
6 Boost Software License - Version 1.0 - August 17th, 2003
7
8 Permission is hereby granted, free of charge, to any person or organization
9 obtaining a copy of the software and accompanying documentation covered by
10 this license (the "Software") to use, reproduce, display, distribute,
11 execute, and transmit the Software, and to prepare derivative works of the
12 Software, and to permit third-parties to whom the Software is furnished to
13 do so, all subject to the following:
14
15 The copyright notices in the Software and this entire statement, including
16 the above license grant, this restriction and the following disclaimer,
17 must be included in all copies of the Software, in whole or in part, and
18 all derivative works of the Software, unless such copies or derivative
19 works are solely in the form of machine-executable object code generated by
20 a source language processor.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
25 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
26 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
29 */
30
31 #include "../../../include/boost/outcome.hpp"
32 #include <algorithm>
33 #include <ctype.h>
34 #include <string>
35 #include <system_error>
36
37 //! [namespace]
38 namespace outcome = BOOST_OUTCOME_V2_NAMESPACE;
39 //! [namespace]
40
41 //! [convert_decl]
42 outcome::result<int> convert(const std::string& str) noexcept;
43 //! [convert_decl]
44
45 //! [enum]
46 enum class ConversionErrc
47 {
48   Success     = 0, // 0 should not represent an error
49   EmptyString = 1, // (for rationale, see tutorial on error codes)
50   IllegalChar = 2,
51   TooLong     = 3,
52 };
53
54 // all boilerplate necessary to plug ConversionErrc
55 // into std::error_code framework
56 //! [enum]
57
58 std::error_code make_error_code(ConversionErrc);
59
60 namespace std {
61     template <> struct is_error_code_enum<ConversionErrc> : true_type {};
62 }
63
64 //! [convert]
65 outcome::result<int> convert(const std::string& str) noexcept
66 {
67   if (str.empty())
68     return ConversionErrc::EmptyString;
69
70   if (!std::all_of(str.begin(), str.end(), ::isdigit))
71     return ConversionErrc::IllegalChar;
72
73   if (str.length() > 9)
74     return ConversionErrc::TooLong;
75
76   return atoi(str.c_str());
77 }
78 //! [convert]
79
80 namespace
81 {
82   struct ConversionErrorCategory : std::error_category
83   {
84     const char* name() const noexcept override { return "bad-convert"; }
85     std::string message(int ev) const override;
86   };
87
88   std::string ConversionErrorCategory::message(int ev) const
89   {
90     switch (static_cast<ConversionErrc>(ev))
91     {
92     case ConversionErrc::Success:
93       return "conversion successful";
94     case ConversionErrc::EmptyString:
95       return "empty string provided";
96     case ConversionErrc::IllegalChar:
97       return "non-digit char provided";
98     case ConversionErrc::TooLong:
99       return "converted int would be too large";
100     }
101       return "(UNCHARTED)";
102   }
103
104   const ConversionErrorCategory globalConversionErrorCategory {};
105 }
106
107 std::error_code make_error_code(ConversionErrc e)
108 {
109   return std::error_code{static_cast<int>(e), globalConversionErrorCategory};
110 }
111
112 void explicit_construction()
113 {
114 //! [explicit]
115 outcome::result<int> r {outcome::in_place_type<std::error_code>, ConversionErrc::EmptyString};
116 outcome::result<int> s {outcome::in_place_type<int>, 1};
117 //! [explicit]
118 }
119
120 void factory_construction()
121 {
122 //! [factory]
123 outcome::result<int> r = outcome::failure(ConversionErrc::EmptyString);
124 outcome::result<int> s = outcome::success(1);
125 //! [factory]
126 }
127
128 struct BigInt
129 {
130   static outcome::result<BigInt> fromString(const std::string& s);
131   explicit BigInt(const std::string&) {}
132   BigInt half() const { return BigInt{""}; }
133   friend std::ostream& operator<<(std::ostream& o, const BigInt&) { return o << "big int half"; }
134 };
135
136 //! [from_string]
137 /*static*/ outcome::result<BigInt> BigInt::fromString(const std::string& s)
138 //! [from_string]
139 {
140     return BigInt{s};
141 }
142
143 //! [half_decl]
144 outcome::result<void> print_half(const std::string& text);
145 //! [half_decl]
146
147 //! [half_impl]
148 outcome::result<void> print_half(const std::string& text)
149 {
150   if (outcome::result<int> r = convert(text))     // #1
151   {
152     std::cout << (r.value() / 2) << std::endl;    // #2
153   }
154   else
155   {
156     if (r.error() == ConversionErrc::TooLong)     // #3
157     {
158       BOOST_OUTCOME_TRY (i, BigInt::fromString(text));  // #4
159       std::cout << i.half() << std::endl;
160     }
161     else
162     {
163       return r.as_failure();                      // #5
164     }
165   }
166   return outcome::success();                      // #6
167 }
168 //! [half_impl]
169
170 //! [tryv]
171 outcome::result<void> test()
172 {
173   BOOST_OUTCOME_TRY ((print_half("2")));
174   BOOST_OUTCOME_TRY ((print_half("X")));
175   BOOST_OUTCOME_TRY ((print_half("4"))); // will not execute
176   return outcome::success();
177 }
178 //! [tryv]
179
180 int main()
181 {
182   if (outcome::result<void> r = print_half("1299999999999999999999999999"))
183   {
184     std::cout << "ok" << std::endl;
185   }
186   else
187   {
188     std::cout << r.error() << std::endl;
189   }
190
191   (void)test();
192 }