Skip to content

Commit e4385da

Browse files
fix: Compiled expected example failed
reason: Missing Destructor specified feat: Add Issue Board to see the Issue Status
1 parent defb169 commit e4385da

2 files changed

Lines changed: 117 additions & 89 deletions

File tree

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,13 @@ python3 scripts/analyze_frontmatter.py
182182

183183
---
184184

185+
## 📌 Issue清单
186+
187+
| ID | Title | Status | Description |
188+
|----|------|--------|------------|
189+
| #1 | expected 实现问题 | 🟡 推送处理等待反馈 | union + std::string 析构问题 |
190+
191+
185192
## 🤝 贡献指南
186193

187194
我们欢迎任何形式的贡献!

codes_and_assets/examples/chapter08/05_expected/expected.hpp

Lines changed: 110 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -2,105 +2,126 @@
22
// 简化的 std::expected 实现(C++17)
33

44
#pragma once
5-
#include <utility>
6-
#include <type_traits>
75
#include <stdexcept>
86
#include <string>
7+
#include <type_traits>
8+
#include <utility>
99

1010
// 用于构造错误分支的辅助类型
11-
template <typename E>
12-
struct unexpected {
13-
E value;
11+
template <typename E> struct unexpected {
12+
E value;
1413
};
1514

16-
template <typename T, typename E>
17-
class expected {
18-
bool has_value_;
19-
union {
20-
T val_;
21-
E err_;
22-
} storage_;
15+
template <typename T, typename E> class expected {
16+
bool has_value_;
17+
union Storage {
18+
T val_;
19+
E err_;
20+
/*
21+
Issue: expected compiled failed #1
22+
See:
23+
https://github.com/Awesome-Embedded-Learning-Studio/Tutorial_AwesomeModernCPP/issues/1
24+
因为 union 包含非平凡构造/析构成员时,编译器会删除其默认构造函数和析构函数。
25+
导致 enclosing class 在构造 storage_ 时失败。必须手动提供空构造/析构。
26+
*/
27+
Storage() {}
28+
~Storage() {}
29+
} storage_;
2330

2431
public:
25-
// 构造成功值
26-
expected(const T& v) : has_value_(true) { new(&storage_.val_) T(v); }
27-
expected(T&& v) : has_value_(true) { new(&storage_.val_) T(std::move(v)); }
28-
29-
// 构造错误
30-
expected(unexpected<E> u) : has_value_(false) { new(&storage_.err_) E(std::move(u.value)); }
31-
32-
// 拷贝/移动构造(简化版)
33-
expected(const expected& other) : has_value_(other.has_value_) {
34-
if (has_value_) {
35-
new(&storage_.val_) T(other.storage_.val_);
36-
} else {
37-
new(&storage_.err_) E(other.storage_.err_);
38-
}
39-
}
40-
41-
expected(expected&& other) noexcept : has_value_(other.has_value_) {
42-
if (has_value_) {
43-
new(&storage_.val_) T(std::move(other.storage_.val_));
44-
} else {
45-
new(&storage_.err_) E(std::move(other.storage_.err_));
46-
}
47-
}
48-
49-
// 析构
50-
~expected() {
51-
if (has_value_) storage_.val_.~T(); else storage_.err_.~E();
52-
}
53-
54-
// 赋值运算符
55-
expected& operator=(const expected& other) {
56-
if (this != &other) {
57-
if (has_value_) storage_.val_.~T(); else storage_.err_.~E();
58-
has_value_ = other.has_value_;
59-
if (has_value_) {
60-
new(&storage_.val_) T(other.storage_.val_);
61-
} else {
62-
new(&storage_.err_) E(other.storage_.err_);
63-
}
64-
}
65-
return *this;
32+
// 构造成功值
33+
expected(const T &v) : has_value_(true) { new (&storage_.val_) T(v); }
34+
expected(T &&v) : has_value_(true) { new (&storage_.val_) T(std::move(v)); }
35+
36+
// 构造错误
37+
expected(unexpected<E> u) : has_value_(false) {
38+
new (&storage_.err_) E(std::move(u.value));
39+
}
40+
41+
// 拷贝/移动构造(简化版)
42+
expected(const expected &other) : has_value_(other.has_value_) {
43+
if (has_value_) {
44+
new (&storage_.val_) T(other.storage_.val_);
45+
} else {
46+
new (&storage_.err_) E(other.storage_.err_);
6647
}
48+
}
6749

68-
bool has_value() const noexcept { return has_value_; }
69-
explicit operator bool() const noexcept { return has_value_; }
70-
71-
T& value() {
72-
if (!has_value_) throw std::runtime_error("bad expected access");
73-
return storage_.val_;
74-
}
75-
76-
const T& value() const {
77-
if (!has_value_) throw std::runtime_error("bad expected access");
78-
return storage_.val_;
79-
}
80-
81-
const E& error() const {
82-
if (has_value_) throw std::runtime_error("no error present");
83-
return storage_.err_;
50+
expected(expected &&other) noexcept : has_value_(other.has_value_) {
51+
if (has_value_) {
52+
new (&storage_.val_) T(std::move(other.storage_.val_));
53+
} else {
54+
new (&storage_.err_) E(std::move(other.storage_.err_));
8455
}
85-
86-
// 简单的 value_or
87-
T value_or(T default_value) const {
88-
if (has_value_) return storage_.val_;
89-
return default_value;
90-
}
91-
92-
// map:将成功值用函数 f 转换为另一个 expected
93-
template <typename F>
94-
auto map(F f) const -> expected<decltype(f(std::declval<T>())), E> {
95-
using U = decltype(f(std::declval<T>()));
96-
if (has_value_) return expected<U, E>(f(storage_.val_));
97-
return expected<U, E>(unexpected<E>{storage_.err_});
98-
}
99-
100-
// and_then:链式调用,f 返回 expected<U, E>
101-
template <typename F>
102-
auto and_then(F f) const -> decltype(f(std::declval<T>())) {
103-
if (has_value_) return f(storage_.val_);
104-
return decltype(f(std::declval<T>()))(unexpected<E>{storage_.err_});
56+
}
57+
58+
// 析构
59+
~expected() {
60+
if (has_value_)
61+
storage_.val_.~T();
62+
else
63+
storage_.err_.~E();
64+
}
65+
66+
// 赋值运算符
67+
expected &operator=(const expected &other) {
68+
if (this != &other) {
69+
if (has_value_)
70+
storage_.val_.~T();
71+
else
72+
storage_.err_.~E();
73+
has_value_ = other.has_value_;
74+
if (has_value_) {
75+
new (&storage_.val_) T(other.storage_.val_);
76+
} else {
77+
new (&storage_.err_) E(other.storage_.err_);
78+
}
10579
}
80+
return *this;
81+
}
82+
83+
bool has_value() const noexcept { return has_value_; }
84+
explicit operator bool() const noexcept { return has_value_; }
85+
86+
T &value() {
87+
if (!has_value_)
88+
throw std::runtime_error("bad expected access");
89+
return storage_.val_;
90+
}
91+
92+
const T &value() const {
93+
if (!has_value_)
94+
throw std::runtime_error("bad expected access");
95+
return storage_.val_;
96+
}
97+
98+
const E &error() const {
99+
if (has_value_)
100+
throw std::runtime_error("no error present");
101+
return storage_.err_;
102+
}
103+
104+
// 简单的 value_or
105+
T value_or(T default_value) const {
106+
if (has_value_)
107+
return storage_.val_;
108+
return default_value;
109+
}
110+
111+
// map:将成功值用函数 f 转换为另一个 expected
112+
template <typename F>
113+
auto map(F f) const -> expected<decltype(f(std::declval<T>())), E> {
114+
using U = decltype(f(std::declval<T>()));
115+
if (has_value_)
116+
return expected<U, E>(f(storage_.val_));
117+
return expected<U, E>(unexpected<E>{storage_.err_});
118+
}
119+
120+
// and_then:链式调用,f 返回 expected<U, E>
121+
template <typename F>
122+
auto and_then(F f) const -> decltype(f(std::declval<T>())) {
123+
if (has_value_)
124+
return f(storage_.val_);
125+
return decltype(f(std::declval<T>()))(unexpected<E>{storage_.err_});
126+
}
106127
};

0 commit comments

Comments
 (0)