Guest User

Untitled

a guest
Nov 22nd, 2017
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.27 KB | None | 0 0
  1. #include <cassert>
  2. #include <iostream>
  3.  
  4. #include <string>
  5. #include <stdexcept>
  6. using namespace std::literals;
  7.  
  8. //#define NYI throw std::runtime_error("line "s + std::to_string(__LINE__) + ": Not yet implemented"s)
  9.  
  10. //
  11. //
  12. //
  13.  
  14. /*
  15. A type that can store one of two values: one representing success
  16. (Ok state) and one representing failure (Err state).
  17.  
  18. When default constructed, Result is in Ok state.
  19.  
  20. Type is Regular if T and E are Regular.
  21.  
  22. Type is Swappable if T and E are Swappable.
  23.  
  24. Do not use Result value that was moved from. Assign a value to it
  25. first (or emplace), then use it. This is standard practice, but
  26. compiler can't enforce it.
  27.  
  28. C++14 compatible.
  29.  
  30. TODO: valueless by exception?
  31. */
  32.  
  33. #include <type_traits>
  34. #include <new>
  35. #include <initializer_list>
  36.  
  37. struct in_place_ok_t {};
  38. constexpr in_place_ok_t const in_place_ok;
  39.  
  40. struct in_place_err_t {};
  41. constexpr in_place_err_t const in_place_err;
  42.  
  43. template<class T, class E>
  44. class Result {
  45.  
  46. enum class Type { Ok, Err, None };
  47.  
  48. using Storage = std::aligned_union_t<1, T, E>;
  49.  
  50. public: // ctor, dtor, assign
  51.  
  52. Result()
  53. : m_type{Type::Ok}
  54. {
  55. new (ptr_ok()) T{};
  56. }
  57.  
  58. Result(Result const& other)
  59. : m_type{other.m_type}
  60. {
  61. if(other.is_ok()) {
  62. new (ptr_ok()) T{*other.ptr_ok()};
  63. }
  64. if(other.is_err()) {
  65. new (ptr_err()) E{*other.ptr_err()};
  66. }
  67. }
  68.  
  69. Result(Result&& other)
  70. : m_type{other.m_type}
  71. {
  72. if(other.is_ok()) {
  73. new (ptr_ok()) T{std::move(*other.ptr_ok())};
  74. }
  75. if(other.is_err()) {
  76. new (ptr_err()) E{std::move(*other.ptr_err())};
  77. }
  78. other.m_type = Type::None;
  79. }
  80.  
  81. template<class ... Args>
  82. Result(in_place_ok_t, Args&& ... args)
  83. : m_type{Type::Ok}
  84. {
  85. new (ptr_ok()) T{std::forward<Args>(args)...};
  86. }
  87.  
  88. template<class U, class ... Args>
  89. Result(in_place_ok_t, std::initializer_list<U> ls, Args&& ... args)
  90. : m_type{Type::Ok}
  91. {
  92. new (ptr_ok()) T{ls, std::forward<Args>(args)...};
  93. }
  94.  
  95. template<class ... Args>
  96. Result(in_place_err_t, Args&& ... args)
  97. : m_type{Type::Err}
  98. {
  99. new (ptr_err()) E{std::forward<Args>(args)...};
  100. }
  101.  
  102. template<class U, class ... Args>
  103. Result(in_place_err_t, std::initializer_list<U> ls, Args&& ... args)
  104. : m_type{Type::Err}
  105. {
  106. new (ptr_err()) E{ls, std::forward<Args>(args)...};
  107. }
  108.  
  109. ~Result() {
  110. deinit();
  111. }
  112.  
  113. Result& operator= (Result const& other) {
  114. if(this != &other) {
  115. deinit();
  116. if(other.is_ok()) {
  117. new (ptr_ok()) T{*other.ptr_ok()};
  118. }
  119. if(other.is_err()) {
  120. new (ptr_err()) E{*other.ptr_err()};
  121. }
  122. m_type = other.m_type;
  123. other.deinit();
  124. }
  125. return *this;
  126. }
  127.  
  128. Result& operator= (Result&& other) {
  129. if(this != &other) {
  130. deinit();
  131. if(other.is_ok()) {
  132. new (ptr_ok()) T{std::move(*other.ptr_ok())};
  133. }
  134. if(other.is_err()) {
  135. new (ptr_err()) E{std::move(*other.ptr_err())};
  136. }
  137. m_type = other.m_type;
  138. other.deinit();
  139. }
  140. return *this;
  141. }
  142.  
  143. public: // equality comparable
  144.  
  145. friend auto operator== (Result const& a, Result const& b) -> bool {
  146. bool result = false;
  147. if(a.m_type == b.m_type) {
  148. if(a.is_ok()) {
  149. result = *a.ptr_ok() == *b.ptr_ok();
  150. }
  151. if(a.is_err()) {
  152. result = *a.ptr_err() == *b.ptr_err();
  153. }
  154. // two Nones are not equal!
  155. }
  156. return result;
  157. }
  158.  
  159. friend auto operator!= (Result const& a, Result const& b) -> bool {
  160. return !(a == b);
  161. }
  162.  
  163. public: // observers
  164.  
  165. auto is_ok() const -> bool {
  166. return Type::Ok == m_type;
  167. }
  168.  
  169. auto is_err() const -> bool {
  170. return Type::Err == m_type;
  171. }
  172.  
  173. auto ok() & -> T& {
  174. assert(is_ok());
  175. return *ptr_ok();
  176. }
  177.  
  178. auto ok() const & -> T const& {
  179. assert(is_ok());
  180. return *ptr_ok();
  181. }
  182.  
  183. auto ok() && -> T&& {
  184. assert(is_ok());
  185. return std::move(*ptr_ok());
  186. }
  187.  
  188. auto ok() const && -> T const&& {
  189. assert(is_ok());
  190. return std::move(*ptr_ok());
  191. }
  192.  
  193. auto err() & -> E& {
  194. assert(is_err());
  195. return *ptr_err();
  196. }
  197.  
  198. auto err() const & -> E const& {
  199. assert(is_err());
  200. return *ptr_err();
  201. }
  202.  
  203. auto err() && -> E&& {
  204. assert(is_err());
  205. return std::move(*ptr_err());
  206. }
  207.  
  208. auto err() const && -> E const&& {
  209. assert(is_err());
  210. return std::move(*ptr_err());
  211. }
  212.  
  213. public: //
  214.  
  215. auto unwrap() & -> T {
  216. assert(is_ok());
  217. return *ptr_ok();
  218. }
  219.  
  220. auto unwrap() const& -> T {
  221. assert(is_ok());
  222. return *ptr_ok();
  223. }
  224.  
  225. auto unwrap() && -> T&& {
  226. assert(is_ok());
  227. return std::move(*ptr_ok());
  228. }
  229.  
  230. auto unwrap() const&& -> T const&& {
  231. assert(is_ok());
  232. return std::move(*ptr_ok());
  233. }
  234.  
  235. public: // swap
  236.  
  237. auto swap(Result& other) {
  238. Result<T,E> temp(std::move(other));
  239. other = std::move(*this);
  240. *this = std::move(temp);
  241. }
  242.  
  243. public: // modifiers
  244.  
  245. template<class ... Args>
  246. auto emplace_ok(Args&& ... args) -> T& {
  247. deinit();
  248. m_type = Type::Ok;
  249. new (ptr_ok()) T{std::forward<Args>(args)...};
  250. return *ptr_ok();
  251. }
  252.  
  253. template<class U, class ... Args>
  254. auto emplace_ok(std::initializer_list<U> ls, Args&& ... args) -> T& {
  255. deinit();
  256. m_type = Type::Ok;
  257. new (ptr_ok()) T{ls, std::forward<Args>(args)...};
  258. return *ptr_ok();
  259. }
  260.  
  261. template<class ... Args>
  262. auto emplace_err(Args&& ... args) -> E& {
  263. deinit();
  264. m_type = Type::Err;
  265. new (ptr_err()) E{std::forward<Args>(args)...};
  266. return *ptr_err();
  267. }
  268.  
  269. template<class U, class ... Args>
  270. auto emplace_err(std::initializer_list<U> ls, Args&& ... args) -> E& {
  271. deinit();
  272. m_type = Type::Err;
  273. new (ptr_err()) E{ls, std::forward<Args>(args)...};
  274. return *ptr_err();
  275. }
  276.  
  277. private: // helpers
  278.  
  279. auto ptr_ok() -> T* {
  280. return reinterpret_cast<T*>(&m_storage);
  281. }
  282.  
  283. auto ptr_ok() const -> T const* {
  284. return reinterpret_cast<T const*>(&m_storage);
  285. }
  286.  
  287. auto ptr_err() -> E* {
  288. return reinterpret_cast<E*>(&m_storage);
  289. }
  290.  
  291. auto ptr_err() const -> E const* {
  292. return reinterpret_cast<E const*>(&m_storage);
  293. }
  294.  
  295. auto deinit() -> void {
  296. if(is_ok()) {
  297. ptr_ok()->~T();
  298. }
  299. if(is_err()) {
  300. ptr_err()->~E();
  301. }
  302. m_type = Type::None;
  303. }
  304.  
  305. private: // fields
  306.  
  307. Type m_type;
  308. Storage m_storage;
  309.  
  310. };
  311.  
  312. template<class T, class E>
  313. auto swap(Result<T, E>& a, Result<T, E>& b) -> void {
  314. a.swap(b);
  315. }
  316.  
  317. //
  318. //
  319. //
  320. #include <vector>
  321. #include <string>
  322.  
  323. struct Test {
  324. Test()
  325. : default_constructed{true}
  326. {}
  327.  
  328. Test(Test const&)
  329. : copy_constructed{true}
  330. {}
  331.  
  332. Test(Test&&)
  333. : move_constructed{true}
  334. {}
  335.  
  336. ~Test() {}
  337.  
  338. Test& operator= (Test const&) {
  339. copy_assigned = true;
  340. return *this;
  341. }
  342.  
  343. Test& operator= (Test&&) {
  344. move_assigned = true;
  345. return *this;
  346. }
  347.  
  348. //
  349. bool default_constructed{false};
  350. bool copy_constructed{false};
  351. bool move_constructed{false};
  352. bool copy_assigned{false};
  353. bool move_assigned{false};
  354. };
  355.  
  356.  
  357. auto main() -> int {
  358.  
  359. //
  360. {
  361. Result<int, std::string> res;
  362.  
  363. assert(res.is_ok());
  364. assert(!res.is_err());
  365. }
  366.  
  367. //
  368. {
  369. std::vector<int> const expected = {1, 2, 3, 4, 5};
  370. Result<std::vector<int>, std::string> res{in_place_ok, {1, 2, 3, 4, 5}};
  371.  
  372. assert(res.ok() == expected);
  373. }
  374.  
  375. //
  376. {
  377. Result<std::vector<int>, std::string> res{in_place_err, "error"};
  378.  
  379. assert(res.err() == "error");
  380. }
  381.  
  382. {
  383. std::vector<int> const expected = {1, 2, 3, 4, 5};
  384. Result<std::vector<int>, std::string> res{in_place_ok, {1, 2, 3, 4, 5}};
  385.  
  386. assert(std::move(res).ok() == expected);
  387. }
  388.  
  389. //
  390. {
  391. Result<std::vector<int>, std::string> res{in_place_err, "error"};
  392.  
  393. assert(std::move(res).err() == "error");
  394. }
  395.  
  396. //
  397. {
  398. Result<int, int> a{in_place_ok, 42}, b{in_place_ok, 42}, c{in_place_ok, 53};
  399.  
  400. assert(a == b);
  401. assert(a != c);
  402. }
  403.  
  404. //
  405. {
  406. Result<int, int> res;
  407.  
  408. assert(res.is_ok());
  409.  
  410. res.emplace_ok(42);
  411.  
  412. assert(res.is_ok() && res.ok() == 42);
  413.  
  414. res.emplace_err(15);
  415.  
  416. assert(res.is_err() && res.err() == 15);
  417. }
  418.  
  419. //
  420. {
  421. Result<int, int> a{in_place_ok, 42}, b{in_place_err, 15};
  422.  
  423. swap(a, b);
  424.  
  425. assert(a.is_err() && a.err() == 15);
  426. assert(b.is_ok() && b.ok() == 42);
  427. }
  428.  
  429. //
  430. {
  431. Result<Test, int> res{};
  432.  
  433. assert(res.ok().default_constructed);
  434.  
  435. res.emplace_ok();
  436.  
  437. assert(res.ok().default_constructed);
  438.  
  439. auto t1 = std::move(res).ok();
  440.  
  441. assert(t1.move_constructed);
  442.  
  443. res.emplace_ok();
  444.  
  445. auto t2 = res.ok();
  446.  
  447. assert(t2.copy_constructed);
  448. }
  449.  
  450. //
  451. {
  452. Result<int, std::string> res{in_place_ok, 42};
  453.  
  454. assert(res.unwrap() == 42);
  455. }
  456.  
  457. }
  458.  
  459. #if 0 // old version using variant
  460. #include <cassert>
  461. #include <iostream>
  462.  
  463. //
  464. //
  465. //
  466. #include <variant>
  467. #include <initializer_list>
  468.  
  469. struct in_place_t {};
  470. constexpr in_place_t const in_place;
  471.  
  472. template<class T>
  473. struct Ok {
  474. Ok() = default;
  475. Ok(Ok const&) = default;
  476. Ok(Ok&&) = default;
  477. ~Ok() = default;
  478. Ok& operator= (Ok const&) = default;
  479. Ok& operator= (Ok&&) = default;
  480.  
  481. Ok(T value_)
  482. : value{std::move(value_)}
  483. {}
  484.  
  485. template<class ... Args>
  486. Ok(in_place_t, Args&& ... args)
  487. : value{std::forward<Args>(args)...}
  488. {}
  489.  
  490. template<class U, class ... Args>
  491. Ok(in_place_t, std::initializer_list<U> ls, Args&& ... args)
  492. : value{ls, std::forward<Args>(args)...}
  493. {}
  494.  
  495. T value;
  496. };
  497.  
  498. template<class T>
  499. auto operator== (Ok<T> const& a, Ok<T> const& b) -> bool {
  500. return a.value == b.value;
  501. }
  502.  
  503. template<class T>
  504. auto operator!= (Ok<T> const& a, Ok<T> const& b) -> bool {
  505. return a.value != b.value;
  506. }
  507.  
  508. template<class E>
  509. struct Err {
  510. Err() = default;
  511. Err(Err const&) = default;
  512. Err(Err&&) = default;
  513. ~Err() = default;
  514. Err& operator= (Err const&) = default;
  515. Err& operator= (Err&&) = default;
  516.  
  517. Err(E e)
  518. : reason{std::move(e)}
  519. {}
  520.  
  521. template<class ... Args>
  522. Err(in_place_t, Args&& ... args)
  523. : reason{std::forward<Args>(args)...}
  524. {}
  525.  
  526. template<class U, class ... Args>
  527. Err(in_place_t, std::initializer_list<U> ls, Args&& ... args)
  528. : reason{ls, std::forward<Args>(args)...}
  529. {}
  530.  
  531.  
  532. E reason;
  533. };
  534.  
  535. template<class E>
  536. auto operator== (Err<E> const& a, Err<E> const& b) -> bool {
  537. return a.reason == b.reason;
  538. }
  539.  
  540. template<class E>
  541. auto operator!= (Err<E> const& a, Err<E> const& b) -> bool {
  542. return a.reason != b.reason;
  543. }
  544.  
  545. struct in_place_ok_t {};
  546. constexpr in_place_ok_t const in_place_ok;
  547.  
  548. struct in_place_err_t {};
  549. constexpr in_place_err_t const in_place_err;
  550.  
  551. template<class T, class E>
  552. class Result {
  553.  
  554. using Ok_ = Ok<T>;
  555. using Err_ = Err<E>;
  556. using Variant = std::variant< Ok_, Err_ >;
  557.  
  558. public: // ctor, dtor, assign
  559.  
  560. Result() = default;
  561.  
  562. Result(Result const& ) = default;
  563.  
  564. Result(Result&& ) = default;
  565.  
  566. template<class ... Args>
  567. Result(in_place_ok_t, Args&& ... args)
  568. : m_variant{ Ok_{ std::forward<Args>(args)... } }
  569. {}
  570.  
  571. template<class U, class ... Args>
  572. Result(in_place_ok_t, std::initializer_list<U> ls, Args&& ... args)
  573. : m_variant{ Ok_{ ls, std::forward<Args>(args)... } }
  574. {}
  575.  
  576. template<class ... Args>
  577. Result(in_place_err_t, Args&& ... args)
  578. : m_variant{ Err_{ E{ std::forward<Args>(args)... } } }
  579. {}
  580.  
  581. template<class U, class ... Args>
  582. Result(in_place_err_t, std::initializer_list<U> ls, Args&& ... args)
  583. : m_variant{ Err_{ E{ ls, std::forward<Args>(args)... } } }
  584. {}
  585.  
  586. ~Result() = default;
  587.  
  588. Result& operator= (Result const& other) = default;
  589.  
  590. Result& operator= (Result&& other) = default;
  591.  
  592. public: // equality comparable
  593.  
  594. friend auto operator== (Result const& a, Result const& b) -> bool {
  595. return a.m_variant == b.m_variant;
  596. }
  597.  
  598. friend auto operator!= (Result const& a, Result const& b) -> bool {
  599. return a.m_variant != b.m_variant;
  600. }
  601.  
  602. public: // observers
  603.  
  604. auto is_ok() const -> bool {
  605. return std::holds_alternative< Ok_ >(m_variant);
  606. }
  607.  
  608. auto is_err() const -> bool {
  609. return std::holds_alternative< Err_ >(m_variant);
  610. }
  611.  
  612. auto ok() & -> T& {
  613. assert(is_ok());
  614. return std::get< Ok_ >(m_variant).value;
  615. }
  616.  
  617. auto ok() const & -> T const& {
  618. assert(is_ok());
  619. return std::get< Ok_ >(m_variant).value;
  620. }
  621.  
  622. auto ok() && -> T&& {
  623. assert(is_ok());
  624. return std::get< Ok_ >(std::move(m_variant)).value;
  625. }
  626.  
  627. auto ok() const && -> T const&& {
  628. assert(is_ok());
  629. return std::get< Ok_ >(std::move(m_variant)).value;
  630. }
  631.  
  632. auto err() & -> E& {
  633. assert(is_err());
  634. return std::get< Err_ >(m_variant).reason;
  635. }
  636.  
  637. auto err() const & -> E const& {
  638. assert(is_err());
  639. return std::get< Err_ >(m_variant).reason;
  640. }
  641.  
  642. auto err() && -> E&& {
  643. assert(is_err());
  644. return std::get< Err_ >(std::move(m_variant)).reason;
  645. }
  646.  
  647. auto err() const && -> E const&& {
  648. assert(is_err());
  649. return std::get< Err_ >(std::move(m_variant)).reason;
  650. }
  651.  
  652. public: // modifiers
  653.  
  654. template<class ... Args>
  655. auto emplace_ok(Args&& ... args) -> T& {
  656. return m_variant.template emplace< Ok_ >( in_place, std::forward<Args>(args)... ).value;
  657. }
  658.  
  659. template<class U, class ... Args>
  660. auto emplace_ok(std::initializer_list<U> ls, Args&& ... args) -> T& {
  661. return m_variant.template emplace< Ok_ >(in_place, ls, std::forward<Args>(args)... ).value;
  662. }
  663.  
  664. template<class ... Args>
  665. auto emplace_err(Args&& ... args) -> E& {
  666. return m_variant.template emplace< Err_ >(in_place, std::forward<Args>(args)... ).reason;
  667. }
  668.  
  669. template<class U, class ... Args>
  670. auto emplace_err(std::initializer_list<U> ls, Args&& ... args) -> E& {
  671. return m_variant.template emplace< Err_ >(in_place, ls, std::forward<Args>(args)... ).reason;
  672. }
  673.  
  674.  
  675. private:
  676. Variant m_variant;
  677. };
  678.  
  679. //
  680. //
  681. //
  682. #include <vector>
  683. #include <string>
  684.  
  685. auto main() -> int {
  686. //
  687. {
  688. Result<int, std::string> res;
  689.  
  690. assert(res.is_ok());
  691. assert(!res.is_err());
  692. }
  693.  
  694. //
  695. {
  696. std::vector<int> const expected = {1, 2, 3, 4, 5};
  697. Result<std::vector<int>, std::string> res{in_place_ok, {1, 2, 3, 4, 5}};
  698.  
  699. assert(res.ok() == expected);
  700. }
  701.  
  702. //
  703. {
  704. Result<std::vector<int>, std::string> res{in_place_err, "error"};
  705.  
  706. assert(res.err() == "error");
  707. }
  708.  
  709. {
  710. std::vector<int> const expected = {1, 2, 3, 4, 5};
  711. Result<std::vector<int>, std::string> res{in_place_ok, {1, 2, 3, 4, 5}};
  712.  
  713. assert(std::move(res).ok() == expected);
  714. }
  715.  
  716. //
  717. {
  718. Result<std::vector<int>, std::string> res{in_place_err, "error"};
  719.  
  720. assert(std::move(res).err() == "error");
  721. }
  722.  
  723. //
  724. {
  725. Result<int, int> a{in_place_ok, 42}, b{in_place_ok, 42}, c{in_place_ok, 53};
  726.  
  727. assert(a == b);
  728. assert(a != c);
  729. }
  730.  
  731. //
  732. {
  733. Result<int, int> res;
  734.  
  735. assert(res.is_ok());
  736.  
  737. res.emplace_ok(42);
  738.  
  739. assert(res.is_ok() && res.ok() == 42);
  740.  
  741. res.emplace_err(15);
  742.  
  743. assert(res.is_err() && res.err() == 15);
  744. }
  745.  
  746. //
  747. {
  748. }
  749. }
  750. #endif
Add Comment
Please, Sign In to add comment