Mercurial > minori
comparison dep/toml11/toml/result.hpp @ 318:3b355fa948c7
config: use TOML instead of INI
unfortunately, INI is not enough, and causes some paths including
semicolons to break with our current storage of the library folders.
so, I decided to switch to TOML which does support real arrays...
| author | Paper <paper@paper.us.eu.org> |
|---|---|
| date | Wed, 12 Jun 2024 05:25:41 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 317:b1f4d1867ab1 | 318:3b355fa948c7 |
|---|---|
| 1 // Copyright Toru Niina 2017. | |
| 2 // Distributed under the MIT License. | |
| 3 #ifndef TOML11_RESULT_HPP | |
| 4 #define TOML11_RESULT_HPP | |
| 5 #include "traits.hpp" | |
| 6 #include <type_traits> | |
| 7 #include <stdexcept> | |
| 8 #include <utility> | |
| 9 #include <new> | |
| 10 #include <string> | |
| 11 #include <sstream> | |
| 12 #include <cassert> | |
| 13 | |
| 14 namespace toml | |
| 15 { | |
| 16 | |
| 17 template<typename T> | |
| 18 struct success | |
| 19 { | |
| 20 using value_type = T; | |
| 21 value_type value; | |
| 22 | |
| 23 explicit success(const value_type& v) | |
| 24 noexcept(std::is_nothrow_copy_constructible<value_type>::value) | |
| 25 : value(v) | |
| 26 {} | |
| 27 explicit success(value_type&& v) | |
| 28 noexcept(std::is_nothrow_move_constructible<value_type>::value) | |
| 29 : value(std::move(v)) | |
| 30 {} | |
| 31 | |
| 32 template<typename U> | |
| 33 explicit success(U&& v): value(std::forward<U>(v)) {} | |
| 34 | |
| 35 template<typename U> | |
| 36 explicit success(const success<U>& v): value(v.value) {} | |
| 37 template<typename U> | |
| 38 explicit success(success<U>&& v): value(std::move(v.value)) {} | |
| 39 | |
| 40 ~success() = default; | |
| 41 success(const success&) = default; | |
| 42 success(success&&) = default; | |
| 43 success& operator=(const success&) = default; | |
| 44 success& operator=(success&&) = default; | |
| 45 }; | |
| 46 | |
| 47 template<typename T> | |
| 48 struct failure | |
| 49 { | |
| 50 using value_type = T; | |
| 51 value_type value; | |
| 52 | |
| 53 explicit failure(const value_type& v) | |
| 54 noexcept(std::is_nothrow_copy_constructible<value_type>::value) | |
| 55 : value(v) | |
| 56 {} | |
| 57 explicit failure(value_type&& v) | |
| 58 noexcept(std::is_nothrow_move_constructible<value_type>::value) | |
| 59 : value(std::move(v)) | |
| 60 {} | |
| 61 | |
| 62 template<typename U> | |
| 63 explicit failure(U&& v): value(std::forward<U>(v)) {} | |
| 64 | |
| 65 template<typename U> | |
| 66 explicit failure(const failure<U>& v): value(v.value) {} | |
| 67 template<typename U> | |
| 68 explicit failure(failure<U>&& v): value(std::move(v.value)) {} | |
| 69 | |
| 70 ~failure() = default; | |
| 71 failure(const failure&) = default; | |
| 72 failure(failure&&) = default; | |
| 73 failure& operator=(const failure&) = default; | |
| 74 failure& operator=(failure&&) = default; | |
| 75 }; | |
| 76 | |
| 77 template<typename T> | |
| 78 success<typename std::remove_cv<typename std::remove_reference<T>::type>::type> | |
| 79 ok(T&& v) | |
| 80 { | |
| 81 return success< | |
| 82 typename std::remove_cv<typename std::remove_reference<T>::type>::type | |
| 83 >(std::forward<T>(v)); | |
| 84 } | |
| 85 template<typename T> | |
| 86 failure<typename std::remove_cv<typename std::remove_reference<T>::type>::type> | |
| 87 err(T&& v) | |
| 88 { | |
| 89 return failure< | |
| 90 typename std::remove_cv<typename std::remove_reference<T>::type>::type | |
| 91 >(std::forward<T>(v)); | |
| 92 } | |
| 93 | |
| 94 inline success<std::string> ok(const char* literal) | |
| 95 { | |
| 96 return success<std::string>(std::string(literal)); | |
| 97 } | |
| 98 inline failure<std::string> err(const char* literal) | |
| 99 { | |
| 100 return failure<std::string>(std::string(literal)); | |
| 101 } | |
| 102 | |
| 103 | |
| 104 template<typename T, typename E> | |
| 105 struct result | |
| 106 { | |
| 107 using value_type = T; | |
| 108 using error_type = E; | |
| 109 using success_type = success<value_type>; | |
| 110 using failure_type = failure<error_type>; | |
| 111 | |
| 112 result(const success_type& s): is_ok_(true) | |
| 113 { | |
| 114 auto tmp = ::new(std::addressof(this->succ)) success_type(s); | |
| 115 assert(tmp == std::addressof(this->succ)); | |
| 116 (void)tmp; | |
| 117 } | |
| 118 result(const failure_type& f): is_ok_(false) | |
| 119 { | |
| 120 auto tmp = ::new(std::addressof(this->fail)) failure_type(f); | |
| 121 assert(tmp == std::addressof(this->fail)); | |
| 122 (void)tmp; | |
| 123 } | |
| 124 result(success_type&& s): is_ok_(true) | |
| 125 { | |
| 126 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); | |
| 127 assert(tmp == std::addressof(this->succ)); | |
| 128 (void)tmp; | |
| 129 } | |
| 130 result(failure_type&& f): is_ok_(false) | |
| 131 { | |
| 132 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); | |
| 133 assert(tmp == std::addressof(this->fail)); | |
| 134 (void)tmp; | |
| 135 } | |
| 136 | |
| 137 template<typename U> | |
| 138 result(const success<U>& s): is_ok_(true) | |
| 139 { | |
| 140 auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); | |
| 141 assert(tmp == std::addressof(this->succ)); | |
| 142 (void)tmp; | |
| 143 } | |
| 144 template<typename U> | |
| 145 result(const failure<U>& f): is_ok_(false) | |
| 146 { | |
| 147 auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); | |
| 148 assert(tmp == std::addressof(this->fail)); | |
| 149 (void)tmp; | |
| 150 } | |
| 151 template<typename U> | |
| 152 result(success<U>&& s): is_ok_(true) | |
| 153 { | |
| 154 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); | |
| 155 assert(tmp == std::addressof(this->succ)); | |
| 156 (void)tmp; | |
| 157 } | |
| 158 template<typename U> | |
| 159 result(failure<U>&& f): is_ok_(false) | |
| 160 { | |
| 161 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); | |
| 162 assert(tmp == std::addressof(this->fail)); | |
| 163 (void)tmp; | |
| 164 } | |
| 165 | |
| 166 result& operator=(const success_type& s) | |
| 167 { | |
| 168 this->cleanup(); | |
| 169 this->is_ok_ = true; | |
| 170 auto tmp = ::new(std::addressof(this->succ)) success_type(s); | |
| 171 assert(tmp == std::addressof(this->succ)); | |
| 172 (void)tmp; | |
| 173 return *this; | |
| 174 } | |
| 175 result& operator=(const failure_type& f) | |
| 176 { | |
| 177 this->cleanup(); | |
| 178 this->is_ok_ = false; | |
| 179 auto tmp = ::new(std::addressof(this->fail)) failure_type(f); | |
| 180 assert(tmp == std::addressof(this->fail)); | |
| 181 (void)tmp; | |
| 182 return *this; | |
| 183 } | |
| 184 result& operator=(success_type&& s) | |
| 185 { | |
| 186 this->cleanup(); | |
| 187 this->is_ok_ = true; | |
| 188 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s)); | |
| 189 assert(tmp == std::addressof(this->succ)); | |
| 190 (void)tmp; | |
| 191 return *this; | |
| 192 } | |
| 193 result& operator=(failure_type&& f) | |
| 194 { | |
| 195 this->cleanup(); | |
| 196 this->is_ok_ = false; | |
| 197 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f)); | |
| 198 assert(tmp == std::addressof(this->fail)); | |
| 199 (void)tmp; | |
| 200 return *this; | |
| 201 } | |
| 202 | |
| 203 template<typename U> | |
| 204 result& operator=(const success<U>& s) | |
| 205 { | |
| 206 this->cleanup(); | |
| 207 this->is_ok_ = true; | |
| 208 auto tmp = ::new(std::addressof(this->succ)) success_type(s.value); | |
| 209 assert(tmp == std::addressof(this->succ)); | |
| 210 (void)tmp; | |
| 211 return *this; | |
| 212 } | |
| 213 template<typename U> | |
| 214 result& operator=(const failure<U>& f) | |
| 215 { | |
| 216 this->cleanup(); | |
| 217 this->is_ok_ = false; | |
| 218 auto tmp = ::new(std::addressof(this->fail)) failure_type(f.value); | |
| 219 assert(tmp == std::addressof(this->fail)); | |
| 220 (void)tmp; | |
| 221 return *this; | |
| 222 } | |
| 223 template<typename U> | |
| 224 result& operator=(success<U>&& s) | |
| 225 { | |
| 226 this->cleanup(); | |
| 227 this->is_ok_ = true; | |
| 228 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(s.value)); | |
| 229 assert(tmp == std::addressof(this->succ)); | |
| 230 (void)tmp; | |
| 231 return *this; | |
| 232 } | |
| 233 template<typename U> | |
| 234 result& operator=(failure<U>&& f) | |
| 235 { | |
| 236 this->cleanup(); | |
| 237 this->is_ok_ = false; | |
| 238 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(f.value)); | |
| 239 assert(tmp == std::addressof(this->fail)); | |
| 240 (void)tmp; | |
| 241 return *this; | |
| 242 } | |
| 243 | |
| 244 ~result() noexcept {this->cleanup();} | |
| 245 | |
| 246 result(const result& other): is_ok_(other.is_ok()) | |
| 247 { | |
| 248 if(other.is_ok()) | |
| 249 { | |
| 250 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
| 251 assert(tmp == std::addressof(this->succ)); | |
| 252 (void)tmp; | |
| 253 } | |
| 254 else | |
| 255 { | |
| 256 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
| 257 assert(tmp == std::addressof(this->fail)); | |
| 258 (void)tmp; | |
| 259 } | |
| 260 } | |
| 261 result(result&& other): is_ok_(other.is_ok()) | |
| 262 { | |
| 263 if(other.is_ok()) | |
| 264 { | |
| 265 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
| 266 assert(tmp == std::addressof(this->succ)); | |
| 267 (void)tmp; | |
| 268 } | |
| 269 else | |
| 270 { | |
| 271 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
| 272 assert(tmp == std::addressof(this->fail)); | |
| 273 (void)tmp; | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 template<typename U, typename F> | |
| 278 result(const result<U, F>& other): is_ok_(other.is_ok()) | |
| 279 { | |
| 280 if(other.is_ok()) | |
| 281 { | |
| 282 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
| 283 assert(tmp == std::addressof(this->succ)); | |
| 284 (void)tmp; | |
| 285 } | |
| 286 else | |
| 287 { | |
| 288 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
| 289 assert(tmp == std::addressof(this->fail)); | |
| 290 (void)tmp; | |
| 291 } | |
| 292 } | |
| 293 template<typename U, typename F> | |
| 294 result(result<U, F>&& other): is_ok_(other.is_ok()) | |
| 295 { | |
| 296 if(other.is_ok()) | |
| 297 { | |
| 298 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
| 299 assert(tmp == std::addressof(this->succ)); | |
| 300 (void)tmp; | |
| 301 } | |
| 302 else | |
| 303 { | |
| 304 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
| 305 assert(tmp == std::addressof(this->fail)); | |
| 306 (void)tmp; | |
| 307 } | |
| 308 } | |
| 309 | |
| 310 result& operator=(const result& other) | |
| 311 { | |
| 312 this->cleanup(); | |
| 313 if(other.is_ok()) | |
| 314 { | |
| 315 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
| 316 assert(tmp == std::addressof(this->succ)); | |
| 317 (void)tmp; | |
| 318 } | |
| 319 else | |
| 320 { | |
| 321 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
| 322 assert(tmp == std::addressof(this->fail)); | |
| 323 (void)tmp; | |
| 324 } | |
| 325 is_ok_ = other.is_ok(); | |
| 326 return *this; | |
| 327 } | |
| 328 result& operator=(result&& other) | |
| 329 { | |
| 330 this->cleanup(); | |
| 331 if(other.is_ok()) | |
| 332 { | |
| 333 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
| 334 assert(tmp == std::addressof(this->succ)); | |
| 335 (void)tmp; | |
| 336 } | |
| 337 else | |
| 338 { | |
| 339 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
| 340 assert(tmp == std::addressof(this->fail)); | |
| 341 (void)tmp; | |
| 342 } | |
| 343 is_ok_ = other.is_ok(); | |
| 344 return *this; | |
| 345 } | |
| 346 | |
| 347 template<typename U, typename F> | |
| 348 result& operator=(const result<U, F>& other) | |
| 349 { | |
| 350 this->cleanup(); | |
| 351 if(other.is_ok()) | |
| 352 { | |
| 353 auto tmp = ::new(std::addressof(this->succ)) success_type(other.as_ok()); | |
| 354 assert(tmp == std::addressof(this->succ)); | |
| 355 (void)tmp; | |
| 356 } | |
| 357 else | |
| 358 { | |
| 359 auto tmp = ::new(std::addressof(this->fail)) failure_type(other.as_err()); | |
| 360 assert(tmp == std::addressof(this->fail)); | |
| 361 (void)tmp; | |
| 362 } | |
| 363 is_ok_ = other.is_ok(); | |
| 364 return *this; | |
| 365 } | |
| 366 template<typename U, typename F> | |
| 367 result& operator=(result<U, F>&& other) | |
| 368 { | |
| 369 this->cleanup(); | |
| 370 if(other.is_ok()) | |
| 371 { | |
| 372 auto tmp = ::new(std::addressof(this->succ)) success_type(std::move(other.as_ok())); | |
| 373 assert(tmp == std::addressof(this->succ)); | |
| 374 (void)tmp; | |
| 375 } | |
| 376 else | |
| 377 { | |
| 378 auto tmp = ::new(std::addressof(this->fail)) failure_type(std::move(other.as_err())); | |
| 379 assert(tmp == std::addressof(this->fail)); | |
| 380 (void)tmp; | |
| 381 } | |
| 382 is_ok_ = other.is_ok(); | |
| 383 return *this; | |
| 384 } | |
| 385 | |
| 386 bool is_ok() const noexcept {return is_ok_;} | |
| 387 bool is_err() const noexcept {return !is_ok_;} | |
| 388 | |
| 389 operator bool() const noexcept {return is_ok_;} | |
| 390 | |
| 391 value_type& unwrap() & | |
| 392 { | |
| 393 if(is_err()) | |
| 394 { | |
| 395 throw std::runtime_error("toml::result: bad unwrap: " + | |
| 396 format_error(this->as_err())); | |
| 397 } | |
| 398 return this->succ.value; | |
| 399 } | |
| 400 value_type const& unwrap() const& | |
| 401 { | |
| 402 if(is_err()) | |
| 403 { | |
| 404 throw std::runtime_error("toml::result: bad unwrap: " + | |
| 405 format_error(this->as_err())); | |
| 406 } | |
| 407 return this->succ.value; | |
| 408 } | |
| 409 value_type&& unwrap() && | |
| 410 { | |
| 411 if(is_err()) | |
| 412 { | |
| 413 throw std::runtime_error("toml::result: bad unwrap: " + | |
| 414 format_error(this->as_err())); | |
| 415 } | |
| 416 return std::move(this->succ.value); | |
| 417 } | |
| 418 | |
| 419 value_type& unwrap_or(value_type& opt) & | |
| 420 { | |
| 421 if(is_err()) {return opt;} | |
| 422 return this->succ.value; | |
| 423 } | |
| 424 value_type const& unwrap_or(value_type const& opt) const& | |
| 425 { | |
| 426 if(is_err()) {return opt;} | |
| 427 return this->succ.value; | |
| 428 } | |
| 429 value_type unwrap_or(value_type opt) && | |
| 430 { | |
| 431 if(is_err()) {return opt;} | |
| 432 return this->succ.value; | |
| 433 } | |
| 434 | |
| 435 error_type& unwrap_err() & | |
| 436 { | |
| 437 if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} | |
| 438 return this->fail.value; | |
| 439 } | |
| 440 error_type const& unwrap_err() const& | |
| 441 { | |
| 442 if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} | |
| 443 return this->fail.value; | |
| 444 } | |
| 445 error_type&& unwrap_err() && | |
| 446 { | |
| 447 if(is_ok()) {throw std::runtime_error("toml::result: bad unwrap_err");} | |
| 448 return std::move(this->fail.value); | |
| 449 } | |
| 450 | |
| 451 value_type& as_ok() & noexcept {return this->succ.value;} | |
| 452 value_type const& as_ok() const& noexcept {return this->succ.value;} | |
| 453 value_type&& as_ok() && noexcept {return std::move(this->succ.value);} | |
| 454 | |
| 455 error_type& as_err() & noexcept {return this->fail.value;} | |
| 456 error_type const& as_err() const& noexcept {return this->fail.value;} | |
| 457 error_type&& as_err() && noexcept {return std::move(this->fail.value);} | |
| 458 | |
| 459 | |
| 460 // prerequisities | |
| 461 // F: T -> U | |
| 462 // retval: result<U, E> | |
| 463 template<typename F> | |
| 464 result<detail::return_type_of_t<F, value_type&>, error_type> | |
| 465 map(F&& f) & | |
| 466 { | |
| 467 if(this->is_ok()){return ok(f(this->as_ok()));} | |
| 468 return err(this->as_err()); | |
| 469 } | |
| 470 template<typename F> | |
| 471 result<detail::return_type_of_t<F, value_type const&>, error_type> | |
| 472 map(F&& f) const& | |
| 473 { | |
| 474 if(this->is_ok()){return ok(f(this->as_ok()));} | |
| 475 return err(this->as_err()); | |
| 476 } | |
| 477 template<typename F> | |
| 478 result<detail::return_type_of_t<F, value_type &&>, error_type> | |
| 479 map(F&& f) && | |
| 480 { | |
| 481 if(this->is_ok()){return ok(f(std::move(this->as_ok())));} | |
| 482 return err(std::move(this->as_err())); | |
| 483 } | |
| 484 | |
| 485 // prerequisities | |
| 486 // F: E -> F | |
| 487 // retval: result<T, F> | |
| 488 template<typename F> | |
| 489 result<value_type, detail::return_type_of_t<F, error_type&>> | |
| 490 map_err(F&& f) & | |
| 491 { | |
| 492 if(this->is_err()){return err(f(this->as_err()));} | |
| 493 return ok(this->as_ok()); | |
| 494 } | |
| 495 template<typename F> | |
| 496 result<value_type, detail::return_type_of_t<F, error_type const&>> | |
| 497 map_err(F&& f) const& | |
| 498 { | |
| 499 if(this->is_err()){return err(f(this->as_err()));} | |
| 500 return ok(this->as_ok()); | |
| 501 } | |
| 502 template<typename F> | |
| 503 result<value_type, detail::return_type_of_t<F, error_type&&>> | |
| 504 map_err(F&& f) && | |
| 505 { | |
| 506 if(this->is_err()){return err(f(std::move(this->as_err())));} | |
| 507 return ok(std::move(this->as_ok())); | |
| 508 } | |
| 509 | |
| 510 // prerequisities | |
| 511 // F: T -> U | |
| 512 // retval: U | |
| 513 template<typename F, typename U> | |
| 514 detail::return_type_of_t<F, value_type&> | |
| 515 map_or_else(F&& f, U&& opt) & | |
| 516 { | |
| 517 if(this->is_err()){return std::forward<U>(opt);} | |
| 518 return f(this->as_ok()); | |
| 519 } | |
| 520 template<typename F, typename U> | |
| 521 detail::return_type_of_t<F, value_type const&> | |
| 522 map_or_else(F&& f, U&& opt) const& | |
| 523 { | |
| 524 if(this->is_err()){return std::forward<U>(opt);} | |
| 525 return f(this->as_ok()); | |
| 526 } | |
| 527 template<typename F, typename U> | |
| 528 detail::return_type_of_t<F, value_type&&> | |
| 529 map_or_else(F&& f, U&& opt) && | |
| 530 { | |
| 531 if(this->is_err()){return std::forward<U>(opt);} | |
| 532 return f(std::move(this->as_ok())); | |
| 533 } | |
| 534 | |
| 535 // prerequisities | |
| 536 // F: E -> U | |
| 537 // retval: U | |
| 538 template<typename F, typename U> | |
| 539 detail::return_type_of_t<F, error_type&> | |
| 540 map_err_or_else(F&& f, U&& opt) & | |
| 541 { | |
| 542 if(this->is_ok()){return std::forward<U>(opt);} | |
| 543 return f(this->as_err()); | |
| 544 } | |
| 545 template<typename F, typename U> | |
| 546 detail::return_type_of_t<F, error_type const&> | |
| 547 map_err_or_else(F&& f, U&& opt) const& | |
| 548 { | |
| 549 if(this->is_ok()){return std::forward<U>(opt);} | |
| 550 return f(this->as_err()); | |
| 551 } | |
| 552 template<typename F, typename U> | |
| 553 detail::return_type_of_t<F, error_type&&> | |
| 554 map_err_or_else(F&& f, U&& opt) && | |
| 555 { | |
| 556 if(this->is_ok()){return std::forward<U>(opt);} | |
| 557 return f(std::move(this->as_err())); | |
| 558 } | |
| 559 | |
| 560 // prerequisities: | |
| 561 // F: func T -> U | |
| 562 // toml::err(error_type) should be convertible to U. | |
| 563 // normally, type U is another result<S, F> and E is convertible to F | |
| 564 template<typename F> | |
| 565 detail::return_type_of_t<F, value_type&> | |
| 566 and_then(F&& f) & | |
| 567 { | |
| 568 if(this->is_ok()){return f(this->as_ok());} | |
| 569 return err(this->as_err()); | |
| 570 } | |
| 571 template<typename F> | |
| 572 detail::return_type_of_t<F, value_type const&> | |
| 573 and_then(F&& f) const& | |
| 574 { | |
| 575 if(this->is_ok()){return f(this->as_ok());} | |
| 576 return err(this->as_err()); | |
| 577 } | |
| 578 template<typename F> | |
| 579 detail::return_type_of_t<F, value_type&&> | |
| 580 and_then(F&& f) && | |
| 581 { | |
| 582 if(this->is_ok()){return f(std::move(this->as_ok()));} | |
| 583 return err(std::move(this->as_err())); | |
| 584 } | |
| 585 | |
| 586 // prerequisities: | |
| 587 // F: func E -> U | |
| 588 // toml::ok(value_type) should be convertible to U. | |
| 589 // normally, type U is another result<S, F> and T is convertible to S | |
| 590 template<typename F> | |
| 591 detail::return_type_of_t<F, error_type&> | |
| 592 or_else(F&& f) & | |
| 593 { | |
| 594 if(this->is_err()){return f(this->as_err());} | |
| 595 return ok(this->as_ok()); | |
| 596 } | |
| 597 template<typename F> | |
| 598 detail::return_type_of_t<F, error_type const&> | |
| 599 or_else(F&& f) const& | |
| 600 { | |
| 601 if(this->is_err()){return f(this->as_err());} | |
| 602 return ok(this->as_ok()); | |
| 603 } | |
| 604 template<typename F> | |
| 605 detail::return_type_of_t<F, error_type&&> | |
| 606 or_else(F&& f) && | |
| 607 { | |
| 608 if(this->is_err()){return f(std::move(this->as_err()));} | |
| 609 return ok(std::move(this->as_ok())); | |
| 610 } | |
| 611 | |
| 612 // if *this is error, returns *this. otherwise, returns other. | |
| 613 result and_other(const result& other) const& | |
| 614 { | |
| 615 return this->is_err() ? *this : other; | |
| 616 } | |
| 617 result and_other(result&& other) && | |
| 618 { | |
| 619 return this->is_err() ? std::move(*this) : std::move(other); | |
| 620 } | |
| 621 | |
| 622 // if *this is okay, returns *this. otherwise, returns other. | |
| 623 result or_other(const result& other) const& | |
| 624 { | |
| 625 return this->is_ok() ? *this : other; | |
| 626 } | |
| 627 result or_other(result&& other) && | |
| 628 { | |
| 629 return this->is_ok() ? std::move(*this) : std::move(other); | |
| 630 } | |
| 631 | |
| 632 void swap(result<T, E>& other) | |
| 633 { | |
| 634 result<T, E> tmp(std::move(*this)); | |
| 635 *this = std::move(other); | |
| 636 other = std::move(tmp); | |
| 637 return ; | |
| 638 } | |
| 639 | |
| 640 private: | |
| 641 | |
| 642 static std::string format_error(std::exception const& excpt) | |
| 643 { | |
| 644 return std::string(excpt.what()); | |
| 645 } | |
| 646 template<typename U, typename std::enable_if<!std::is_base_of< | |
| 647 std::exception, U>::value, std::nullptr_t>::type = nullptr> | |
| 648 static std::string format_error(U const& others) | |
| 649 { | |
| 650 std::ostringstream oss; oss << others; | |
| 651 return oss.str(); | |
| 652 } | |
| 653 | |
| 654 void cleanup() noexcept | |
| 655 { | |
| 656 if(this->is_ok_) {this->succ.~success_type();} | |
| 657 else {this->fail.~failure_type();} | |
| 658 return; | |
| 659 } | |
| 660 | |
| 661 private: | |
| 662 | |
| 663 bool is_ok_; | |
| 664 union | |
| 665 { | |
| 666 success_type succ; | |
| 667 failure_type fail; | |
| 668 }; | |
| 669 }; | |
| 670 | |
| 671 template<typename T, typename E> | |
| 672 void swap(result<T, E>& lhs, result<T, E>& rhs) | |
| 673 { | |
| 674 lhs.swap(rhs); | |
| 675 return; | |
| 676 } | |
| 677 | |
| 678 // this might be confusing because it eagerly evaluated, while in the other | |
| 679 // cases operator && and || are short-circuited. | |
| 680 // | |
| 681 // template<typename T, typename E> | |
| 682 // inline result<T, E> | |
| 683 // operator&&(const result<T, E>& lhs, const result<T, E>& rhs) noexcept | |
| 684 // { | |
| 685 // return lhs.is_ok() ? rhs : lhs; | |
| 686 // } | |
| 687 // | |
| 688 // template<typename T, typename E> | |
| 689 // inline result<T, E> | |
| 690 // operator||(const result<T, E>& lhs, const result<T, E>& rhs) noexcept | |
| 691 // { | |
| 692 // return lhs.is_ok() ? lhs : rhs; | |
| 693 // } | |
| 694 | |
| 695 // ---------------------------------------------------------------------------- | |
| 696 // re-use result<T, E> as a optional<T> with none_t | |
| 697 | |
| 698 namespace detail | |
| 699 { | |
| 700 struct none_t {}; | |
| 701 inline bool operator==(const none_t&, const none_t&) noexcept {return true;} | |
| 702 inline bool operator!=(const none_t&, const none_t&) noexcept {return false;} | |
| 703 inline bool operator< (const none_t&, const none_t&) noexcept {return false;} | |
| 704 inline bool operator<=(const none_t&, const none_t&) noexcept {return true;} | |
| 705 inline bool operator> (const none_t&, const none_t&) noexcept {return false;} | |
| 706 inline bool operator>=(const none_t&, const none_t&) noexcept {return true;} | |
| 707 template<typename charT, typename traitsT> | |
| 708 std::basic_ostream<charT, traitsT>& | |
| 709 operator<<(std::basic_ostream<charT, traitsT>& os, const none_t&) | |
| 710 { | |
| 711 os << "none"; | |
| 712 return os; | |
| 713 } | |
| 714 inline failure<none_t> none() noexcept {return failure<none_t>{none_t{}};} | |
| 715 } // detail | |
| 716 } // toml11 | |
| 717 #endif// TOML11_RESULT_H |
