• R/O
  • SSH

posixpp: Commit

The main posixpp library and associated tests.


Commit MetaInfo

Revisionfb5ee525b881762d6d71a476e6a7b144c5d50bdf (tree)
Time2021-04-25 07:45:43
AuthorEric Hopper <hopper@omni...>
CommiterEric Hopper

Log Message

Remove dependency on variant. It uses virtual tables.

Change Summary

Incremental Difference

diff -r 7188050a1ebe -r fb5ee525b881 pubincludes/posixpp/expected.h
--- a/pubincludes/posixpp/expected.h Sat Feb 20 19:28:11 2021 -0800
+++ b/pubincludes/posixpp/expected.h Sat Apr 24 15:45:43 2021 -0700
@@ -3,7 +3,6 @@
33 #include <system_error>
44 #include <utility>
55 #include <stdexcept>
6-#include <variant>
76 #include <concepts>
87
98 namespace posixpp {
@@ -12,16 +11,37 @@
1211 class expected_base {
1312 public:
1413 struct err_tag {}; // Just a type to serve as a tag to indicate error value.
15-
14+/*
1615 struct err_t {
1716 int errval;
1817
1918 err_t(int e) : errval(e) {}
2019 operator int() const { return errval; }
2120 }; // Just a type to serve as a tag to indicate error value.
21+*/
2222 };
23+
2324 }
2425
26+
27+class no_error_here : public ::std::exception
28+{
29+ public:
30+ no_error_here() noexcept { }
31+
32+ char const *what() const noexcept override
33+ {
34+ return reason_;
35+ }
36+
37+ private:
38+ no_error_here(char const *reason) noexcept : reason_(reason) { }
39+
40+ // Must point to a string with static storage duration:
41+ char const *reason_ = "no error in expected when error requested";
42+};
43+
44+
2545 //! A value that may be an error, throws if accessed and is an error.
2646 template <typename T>
2747 class expected : private priv_::expected_base {
@@ -30,47 +50,57 @@
3050 using priv_::expected_base::err_tag;
3151 using result_t = T;
3252
33- explicit expected(T const &val) requires ::std::copyable<T> : val_{val}
53+ explicit constexpr expected(T const &val) noexcept requires ::std::copyable<T>
54+ : val_{val}, has_error_{false}
3455 {}
35- explicit expected(T &&val) requires ::std::movable<T>
36- : val_{::std::move(val)}
56+ explicit constexpr expected(T &&val) noexcept requires ::std::movable<T>
57+ : val_{::std::move(val)}, has_error_{false}
3758 {}
38- explicit expected(err_tag const &, int ec)
59+ explicit constexpr expected(err_tag const &, int ec) noexcept
3960 requires ::std::movable<T> || ::std::copyable<T>
40- : val_{err_t{ec}}
61+ : val_{.errcode_ = ec}, has_error_{true}
4162 {}
42-
43- [[nodiscard]] T &result() requires ::std::movable<T> {
44- if (auto result = ::std::get_if<T>(&val_)) {
45- return *result;
46- } else {
47- auto const &cat = ::std::system_category();
48- throw ::std::system_error(::std::get<err_t>(val_), cat);
63+ constexpr ~expected() noexcept {
64+ if (!has_error_) {
65+ val_.value_.~T();
4966 }
5067 }
5168
52- [[nodiscard]] T const &result() const requires ::std::copyable<T> {
53- if (auto result = ::std::get_if<T>(&val_)) {
54- return *result;
69+ [[nodiscard]] constexpr T &&result() requires ::std::movable<T> {
70+ if (!has_error_) {
71+ return ::std::move(val_.value_);
5572 } else {
5673 auto const &cat = ::std::system_category();
57- throw ::std::system_error(::std::get<err_t>(val_), cat);
74+ throw ::std::system_error(val_.errcode_, cat);
75+ }
76+ }
77+
78+ [[nodiscard]] constexpr T const &result() const requires ::std::copyable<T> {
79+ if (!has_error_) {
80+ return val_.value_;
81+ } else {
82+ auto const &cat = ::std::system_category();
83+ throw ::std::system_error(val_.value_, cat);
5884 }
5985 }
6086
6187 void throw_if_error() const {
62- if (auto error = ::std::get_if<err_t>(&val_)) {
88+ if (has_error_) {
6389 auto const &cat = ::std::system_category();
64- throw ::std::system_error(*error, cat);
90+ throw ::std::system_error(val_.errcode_, cat);
6591 }
6692 }
6793
68- [[nodiscard]] bool has_error() const noexcept {
69- return ::std::holds_alternative<err_t>(val_);
94+ [[nodiscard]] constexpr bool has_error() const noexcept {
95+ return has_error_;
7096 }
7197
72- [[nodiscard]] int error() const {
73- return ::std::get<err_t>(val_);
98+ [[nodiscard]] constexpr int error() const {
99+ if (has_error_) {
100+ return val_.errcode_;
101+ } else {
102+ throw no_error_here{};
103+ }
74104 }
75105
76106 [[nodiscard]] ::std::error_condition error_condition() const {
@@ -78,7 +108,13 @@
78108 }
79109
80110 private:
81- ::std::variant<T, err_t> val_;
111+ union anonymous {
112+ T value_;
113+ int errcode_;
114+
115+ ~anonymous() {} // Destruction handled by expected<T>
116+ } val_;
117+ bool has_error_;
82118 };
83119
84120 //! A value that may be an error, throws if accessed and is an error.
@@ -88,28 +124,32 @@
88124 using priv_::expected_base::err_tag;
89125 using result_t = void;
90126
91- expected() : err_(err_t{0}) {}
92- explicit expected(err_tag const &, int ec) noexcept
93- : err_{err_t{ec}}
127+ expected() : errcode_{0} {}
128+ constexpr explicit expected(int ec) noexcept
129+ : errcode_{ec}
94130 {}
95131
96132 void result() const {
97133 throw_if_error();
98134 }
99135
100- void throw_if_error() const {
101- if (err_ != 0) {
136+ constexpr void throw_if_error() const {
137+ if (errcode_ != 0) {
102138 auto const &cat = ::std::system_category();
103- throw ::std::system_error(err_, cat);
139+ throw ::std::system_error(errcode_, cat);
104140 }
105141 }
106142
107- [[nodiscard]] bool has_error() const noexcept {
108- return err_ != 0;
143+ [[nodiscard]] constexpr bool has_error() const noexcept {
144+ return errcode_ != 0;
109145 }
110146
111- [[nodiscard]] int error() const noexcept {
112- return err_;
147+ [[nodiscard]] constexpr int error() const {
148+ if (errcode_ == 0) {
149+ return errcode_;
150+ } else {
151+ throw no_error_here{};
152+ }
113153 }
114154
115155 [[nodiscard]] ::std::error_condition error_condition() const noexcept {
@@ -117,7 +157,7 @@
117157 }
118158
119159 private:
120- err_t err_;
160+ int errcode_;
121161 };
122162
123163 //! Call converter with result, or cascade error upward.
@@ -158,7 +198,7 @@
158198 using outresult_t = expected<void>;
159199 using errtag = typename outresult_t::err_tag;
160200 if (result.has_error()) {
161- return outresult_t{errtag{}, result.error()};
201+ return outresult_t{result.error()};
162202 } else {
163203 return outresult_t{};
164204 }
diff -r 7188050a1ebe -r fb5ee525b881 tests/expected.cpp
--- a/tests/expected.cpp Sat Feb 20 19:28:11 2021 -0800
+++ b/tests/expected.cpp Sat Apr 24 15:45:43 2021 -0700
@@ -11,8 +11,8 @@
1111 CHECK( result.has_error() == false );
1212 } THEN(" result.throw_if_error() does nothing ") {
1313 CHECK_NOTHROW(result.throw_if_error());
14- } THEN(" result.error() throws bad_variant_access ") {
15- CHECK_THROWS_AS(result.error(), ::std::bad_variant_access);
14+ } THEN(" result.error() throws no_error_here ") {
15+ CHECK_THROWS_AS(result.error(), ::posixpp::no_error_here);
1616 }
1717 }
1818 GIVEN("An expectedd<int> result initialized as an error with ENOENT") {
Show on old repository browser