日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁 > 單片機(jī) > 程序喵大人

前面我寫過一篇推薦使用 std::optional 的文章,而 optional 是C++17 引入的新特性,很多讀者反饋?zhàn)约旱捻?xiàng)目還停留在C++11標(biāo)準(zhǔn),沒辦法使用C++17,也就沒辦法使用 optional,既然不能直接使用 std::optional,我們可以考慮自己實(shí)現(xiàn)一個(gè)。

其實(shí)optional的功能比較明確,它允許變量可能包含值也可能不包含值。

下面我將逐步解釋如何自己實(shí)現(xiàn)一個(gè)簡單的 optional 類

nullopt_t 結(jié)構(gòu)體

struct nullopt_t { struct init {}; constexpr explicit nullopt_t(init) {}};constexpr nullopt_t nullopt{nullopt_t::init()};

		

這里定義一個(gè)nullopt_t,nullopt_t 是一個(gè)特殊類型,用來表示 optional 對象中沒有值。我們定義了一個(gè) init 結(jié)構(gòu)體來確保 nullopt_t 的構(gòu)造函數(shù)是顯式的,避免不必要的隱式轉(zhuǎn)換。

optional 類的構(gòu)造函數(shù)

template <typename T>class optional {public: optional() : has_value_(false) {} optional(nullopt_t) : has_value_(false) {} optional(const T& value) : has_value_(true), value_(value) {} optional(T&& value) : has_value_(true), value_(std::move(value)) {}};

這些構(gòu)造函數(shù)初始化 optional 對象。optional() optional(nullopt_t) 構(gòu)造函數(shù)將 has_value_ 設(shè)置為 false,表示沒有值。其余兩個(gè)構(gòu)造函數(shù)分別接受左值引用和右值引用,初始化 value_ 并將 has_value_ 設(shè)置為 true。

拷貝和移動(dòng)構(gòu)造函數(shù)

optional(const optional& other) : has_value_(other.has_value_), value_(other.value_) {}optional(optional&& other) : has_value_(other.has_value_), value_(std::move(other.value_)) {}

拷貝構(gòu)造函數(shù)和移動(dòng)構(gòu)造函數(shù)用于創(chuàng)建一個(gè)新的 optional 對象,它們分別從另一個(gè) optional 對象中拷貝或移動(dòng)值。

拷貝和移動(dòng)賦值運(yùn)算符

optional& operator=(const optional& other) { if (this != &other) { has_value_ = other.has_value_; value_ = other.value_; } return *this;} optional& operator=(optional&& other) { if (this != &other) { has_value_ = other.has_value_; value_ = std::move(other.value_); } return *this;}

賦值運(yùn)算符用于將一個(gè) optional 對象的值賦給另一個(gè) optional 對象??截愘x值運(yùn)算符從另一個(gè) optional 對象中拷貝值,而移動(dòng)賦值運(yùn)算符則移動(dòng)值方便提高效率。

nullopt_t 賦值運(yùn)算符和普通賦值運(yùn)算符

optional& operator=(nullopt_t) { has_value_ = false; return *this;} optional& operator=(const T& value) { has_value_ = true; value_ = value; return *this;} optional& operator=(T&& value) { has_value_ = true; value_ = std::move(value); return *this;}

這些賦值運(yùn)算符允許我們將 nullopt 或一個(gè)具體值賦給 optional 對象。

檢查值是否存在的方法

bool has_value() const { return has_value_; }

has_value 方法返回一個(gè)布爾值,表示 optional 對象是否包含值。

獲取值的方法

T& value() { if (!has_value_) { throw std::exception(); } return value_;} const T& value() const { if (!has_value_) { throw std::exception(); } return value_;}

value 方法返回 optional 對象中的值,如果沒有值則拋出異常。

返回默認(rèn)值的方法

T value_or(const T& default_value) const { return has_value_ ? value_ : default_value;}

value_or 方法返回 optional 對象中的值,如果沒有值則返回默認(rèn)值。

重載操作符

T& operator()() { return value(); } const T& operator()() const { return value(); } optional& swap(optional& other) { std::swap(has_value_, other.has_value_); std::swap(value_, other.value_); return *this;} T* operator->() { return &value(); } const T* operator->() const { return &value(); } T& operator*() { return value(); } const T& operator*() const { return value(); }

這里又重載了一些操作符,這些使 optional 對象的使用更加便捷。operator() operator* 使得我們可以像使用普通對象一樣使用 optional 對象。operator-> 提供了指針語法的支持。swap 方法交換兩個(gè) optional 對象的值。

私有成員變量

private: bool has_value_; T value_;};

has_value_ 是一個(gè)布爾值,用來表示 optional 對象是否包含值。value_ 存儲實(shí)際的值。

測試代碼

int main() { optional<int> opt1; optional<int> opt2 = 42; optional<int> opt3 = nullopt;  std::cout << "opt1 has value: " << opt1.has_value() << std::endl; std::cout << "opt2 has value: " << opt2.has_value() << std::endl; std::cout << "opt3 has value: " << opt3.has_value() << std::endl;  if (opt2.has_value()) { std::cout << "opt2 value: " << opt2.value() << std::endl; }  opt3 = 10; std::cout << "opt3 value after assignment: " << opt3.value() << std::endl;  opt3 = nullopt; std::cout << "opt3 has value after assigning nullopt: " << opt3.has_value() << std::endl;  try { std::cout << "opt1 value: " << opt1.value() << std::endl; } catch (const std::exception& e) { std::cout << "Exception caught: opt1 has no value" << std::endl; }  optional<int> opt4 = opt2; std::cout << "opt4 value after copy construction: " << opt4.value() << std::endl;  optional<int> opt5 = std::move(opt2); std::cout << "opt5 value after move construction: " << opt5.value() << std::endl;  optional<int> opt6; opt6 = opt4; std::cout << "opt6 value after copy assignment: " << opt6.value() << std::endl;  optional<int> opt7; opt7 = std::move(opt4); std::cout << "opt7 value after move assignment: " << opt7.value() << std::endl;  optional<int> opt8 = 5; std::cout << "opt8 value before swap: " << opt8.value() << std::endl; opt8.swap(opt7); std::cout << "opt8 value after swap: " << opt8.value() << std::endl; std::cout << "opt7 value after swap: " << opt7.value() << std::endl;  std::cout << "opt6 value_or test: " << opt6.value_or(100) << std::endl; std::cout << "opt3 value_or test: " << opt3.value_or(100) << std::endl;  optional<std::string> optStr = std::string("Hello, optional!"); if (optStr.has_value()) { std::cout << "optStr value: " << *optStr << std::endl; }  return 0;}

在這個(gè)測試代碼中,展示了如何使用我們實(shí)現(xiàn)的 optional 類。下面是每個(gè)測試部分的簡要說明:

  1. 默認(rèn)構(gòu)造和空值初始化:

optional<int> opt1;optional<int> opt2 = 42;optional<int> opt3 = nullopt;

創(chuàng)建三個(gè)optional 對象,其中一個(gè)無值,一個(gè)初始化為 42,一個(gè)初始化為 nullopt。

  1. 檢查值是否存在:

std::cout << "opt1 has value: " << opt1.has_value() << std::endl;std::cout << "opt2 has value: " << opt2.has_value() << std::endl;std::cout << "opt3 has value: " << opt3.has_value() << std::endl;

使用 has_value() 方法檢查每個(gè) optional 對象是否包含值。

  1. 獲取值:

if (opt2.has_value()) { std::cout << "opt2 value: " << opt2.value() << std::endl;}

在確保 optional 對象包含值后,使用 value() 方法獲取值。

  1. 賦值操作:

opt3 = 10;std::cout << "opt3 value after assignment: " << opt3.value() << std::endl; opt3 = nullopt;std::cout << "opt3 has value after assigning nullopt: " << opt3.has_value() << std::endl;

展示了如何將值和 nullopt 賦給 optional 對象。

  1. 異常處理:

try { std::cout << "opt1 value: " << opt1.value() << std::endl;} catch (const std::exception& e) { std::cout << "Exception caught: opt1 has no value" << std::endl;}

如果嘗試獲取一個(gè)沒有值的 optional 對象的值,會拋出異常。

  1. 拷貝和移動(dòng)構(gòu)造:

optional<int> opt4 = opt2;std::cout << "opt4 value after copy construction: " << opt4.value() << std::endl; optional<int> opt5 = std::move(opt2);std::cout << "opt5 value after move construction: " << opt5.value() << std::endl;

展示了如何通過拷貝和移動(dòng)構(gòu)造函數(shù)創(chuàng)建 optional 對象。

  1. 拷貝和移動(dòng)賦值:

optional<int> opt6;opt6 = opt4;std::cout << "opt6 value after copy assignment: " << opt6.value() << std::endl; optional<int> opt7;opt7 = std::move(opt4);std::cout << "opt7 value after move assignment: " << opt7.value() << std::endl;

展示了如何通過拷貝和移動(dòng)賦值操作符將值賦給 optional 對象。

  1. 交換值:

optional<int> opt8 = 5;std::cout << "opt8 value before swap: " << opt8.value() << std::endl;opt8.swap(opt7);std::cout << "opt8 value after swap: " << opt8.value() << std::endl;std::cout << "opt7 value after swap: " << opt7.value() << std::endl;
  1. 默認(rèn)值獲?。?/span>

std::cout << "opt6 value_or test: " << opt6.value_or(100) << std::endl;std::cout << "opt3 value_or test: " << opt3.value_or(100) << std::endl;

使用 value_or 方法獲取 optional 對象的值,如果沒有值則返回默認(rèn)值。

10. 字符串類型的 optional

optional<std::string> optStr = std::string("Hello, optional!");if (optStr.has_value()) { std::cout << "optStr value: " << *optStr << std::endl;}

創(chuàng)建一個(gè) optional 對象,并檢查其值。

總結(jié)

通過上述代碼和講解,我們展示了如何實(shí)現(xiàn)一個(gè)簡單的 optional 類。希望本文能幫助你更好地理解 std::optional 的實(shí)現(xiàn)原理。

下面為完整源代碼

#include #include #include  struct nullopt_t { struct init {}; constexpr explicit nullopt_t(init) {}}; constexpr nullopt_t nullopt{nullopt_t::init()}; template <typename T>class optional { public: optional() : has_value_(false) {} optional(nullopt_t) : has_value_(false) {} optional(const T& value) : has_value_(true), value_(value) {} optional(T&& value) : has_value_(true), value_(std::move(value)) {}  optional(const optional& other) : has_value_(other.has_value_), value_(other.value_) {} optional(optional&& other) : has_value_(other.has_value_), value_(std::move(other.value_)) {}  optional& operator=(const optional& other) { if (this != &other) { has_value_ = other.has_value_; value_ = other.value_; } return *this; }  optional& operator=(optional&& other) { if (this != &other) { has_value_ = other.has_value_; value_ = std::move(other.value_); } return *this; }  optional& operator=(nullopt_t) { has_value_ = false; return *this; }  optional& operator=(const T& value) { has_value_ = true; value_ = value; return *this; }  optional& operator=(T&& value) { has_value_ = true; value_ = std::move(value); return *this; }  bool has_value() const { return has_value_; }  T& value() { if (!has_value_) { throw std::exception(); } return value_; }  const T& value() const { if (!has_value_) { throw std::exception(); } return value_; }  T value_or(const T& default_value) const { return has_value_ ? value_ : default_value; }  T& operator()() { return value(); }  const T& operator()() const { return value(); }  optional& swap(optional& other) { std::swap(has_value_, other.has_value_); std::swap(value_, other.value_); return *this; }  T* operator->() { return &value(); }  const T* operator->() const { return &value(); }  T& operator*() { return value(); }  const T& operator*() const { return value(); }  private: bool has_value_; T value_;}; 



本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時(shí)聯(lián)系本站刪除。
關(guān)閉