C++ backports
阅读量:
searchstar
2023-07-17 16:52:29
Categories:
Tags:
¶
std::optional
(since C++17)
#include <iostream>
struct in_place_t {};
inline constexpr in_place_t in_place{};
template <typename T>
class optional {
public:
optional() : has_value_(false) {}
optional(T&& x) : has_value_(true), x_(std::move(x)) {}
optional(
in_place_t, Args&&... args
) : has_value_(true), x_(std::forward<Args>(args)...) {}
optional<T>& operator=(T&& x) {
if (has_value_)
x_.~T();
has_value_ = true;
x_ = std::move(x);
return *this;
}
optional(const optional<T>& rhs) : has_value_(rhs.has_value_) {
if (has_value_) {
x_ = rhs.x_;
}
}
optional<T>& operator=(const optional<T>& rhs) {
this->~optional();
has_value_ = rhs.has_value_;
if (has_value_) {
x_ = rhs.x_;
}
return *this;
}
optional(optional<T>&& rhs) : has_value_(rhs.has_value_) {
if (has_value_) {
x_ = std::move(rhs.x_);
rhs.has_value_ = false;
}
}
optional<T>& operator=(optional<T>&& rhs) {
this->~optional();
has_value_ = rhs.has_value_;
if (has_value_) {
x_ = std::move(rhs.x_);
rhs.has_value_ = false;
}
return *this;
}
~optional() {
if (has_value_) {
x_.~T();
}
}
bool has_value() const { return has_value_; }
T &value() { return x_; }
const T &value() const { return x_; }
void reset() {
if (has_value_) {
x_.~T();
has_value_ = false;
}
}
private:
bool has_value_;
union {
T x_;
};
};
// https://stackoverflow.com/a/9103132/13688160
template <typename T, typename... Args>
optional<T> make_optional(Args &&...args) {
return optional<T>(in_place, std::forward<Args>(args)...);
}
class A {
public:
A(int x) : x_(x) {}
A(A& rhs) : x_(rhs.x_) {}
A& operator=(const A& rhs) {
x_ = rhs.x_;
return *this;
}
A(A&& rhs) : x_(rhs.x_) {
rhs.x_ = 0;
}
A& operator=(A&& rhs) {
x_ = rhs.x_;
rhs.x_ = 0;
return *this;
}
~A() {
std::cout << "~A(): " << x_ << std::endl;
}
private:
int x_;
};
int main() {
std::cout << "1\n";
{
optional<A> x;
}
std::cout << "2\n";
{
make_optional<A>(233);
}
std::cout << "3\n";
{
optional<A> x;
x = A(233);
}
std::cout << "4\n";
{
auto x = make_optional<A>(233);
x = A(466);
}
std::cout << "5\n";
{
auto x = make_optional<A>(233);
auto y = make_optional<A>(466);
x = y;
}
std::cout << "6\n";
{
auto x = make_optional<A>(233);
auto y = make_optional<A>(466);
x = std::move(y);
}
std::cout << "7\n";
{
optional<int> x;
std::cout << x.has_value() << std::endl;
x = 233;
std::cout << x.has_value() << ' ' << x.value() << std::endl;
x.value() = 466;
std::cout << x.has_value() << ' ' << x.value() << std::endl;
}
std::cout << "8\n";
{
auto x = make_optional<A>(233);
x.reset();
}
return 0;
}
1
2
~A(): 0
~A(): 233
3
~A(): 0
~A(): 233
4
~A(): 233
~A(): 0
~A(): 466
5
~A(): 233
~A(): 466
~A(): 466
6
~A(): 233
~A(): 466
7
0
1 233
1 466
8
~A(): 233