318
+ − 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