C++ 23 可以回傳值或錯誤的 std::expected

之前在《更多元的函式回傳型別:optional 與 outcome》這篇文章中,曾經提過在函式需要回傳計算的結果,但是又可能需要回傳處理的狀態(包含錯誤)的時候,除了可以使用簡單的 C++17 的 std::optional 來處理沒有辦法回傳值的狀況外,下面就是一個簡單的例子:

#include <iostream>
#include <optional>
 
std::optional<int> compute_opt(const int input)
{
  if (input == 0 || input > 100)
    return std::nullopt;
 
  return 100 / input;
}
 
int main(int argc, char** argv)
{
  auto optRes = compute_opt(101);
  if (optRes)
    std::cout << "OK: " << *optRes << std::endl;
  else
    std::cout << "Error" << std::endl;
}

閱讀更多»

廣告

透過 counting_iterator 讓 std::for_each_n 用索引值來操作

C++ 的標準函式庫雖然一直以來都有提供 <algorithm> 這個函式庫(參考),可以來做某些處理;而裡面其實也有像是 std::for_each()參考)或 std::for_each_n()參考)這類的函式、可以用來掃完整個陣列。

但是由於這些演算法大多是針對 iterator 來進行操作,在很多需要使用索引值(index)來存取周圍的資料時,會變得相對麻煩;也因此,其實 Heresy 這邊大多會使用傳統的 for 迴圈、或是 C++11 的 range-base for-loop 來寫,而很少會去用 std::for_each()

也因此,當 C++17 開始正式針對部分也算法提供平行化的能力的時候(參考),雖然高興了一陣子,但是卻也發現有點難以使用…

閱讀更多»

更多元的函式回傳型別:optional 與 outcome

一般當在設計函式介面的時候,都會直接把結果回傳出來;比如說:

int compute(const int input)
{
  return 100 / input;
}

這樣的設計非常直覺,但是像以上面的例子來說,如果 input 是 0 的時候,這個函式就會產生例外狀況(exception)了。

而如果我們想要用 exception 以外的形式,來處理這類的錯誤的話,通常就需要修改函式的介面,讓他可以回傳執行的狀況。

閱讀更多»

儲存 C++ 的類別資料:Boost Serialization(part 2)

前一篇 part 1 大致上把 Boost serialization 的基本使用整理了一下。接下來這篇,就繼續整理一下其他的東西吧~


將 serialize() 改成 private

首先,在之前提到的例子裡面,如果是選擇在類別中定義成員函式 serialize() 的時候, 是直接把它定義成 public 的。

但是考慮到這個函式的特殊性,或許他並不適合做為一個外部可以直接呼叫的 public 函式。

所以這邊比較好的做法,應該是將它改為 private、並透過設定 friend class、來讓它可以被 Boost serialization 提供的 archive 呼叫,理論上會比較安全。

閱讀更多»

儲存 C++ 的類別資料:Boost Serialization(part 1)

「Serialization」(序列化、維基百科)在程式語言裡面,基本上是一種用來把資料結構或是物件的狀態,轉換成可儲存、可交換的格式的一種方法。
透過這樣的功能,可以把物件的狀態儲存下、之後再還原回來。

XML、JSON 這類的格式,實際上都可以算是序列化資料格式的一種。

而在 C++ 的標準函式庫中,並沒有提供相關的功能,所以這邊 Heresy 是找 Boost C++ Libraries 的 Boost.Serialization 來用了。

他的官方文件是:https://www.boost.org/libs/serialization/doc/index.html

閱讀更多»

Boost ASIO WebSocket Server 網站憑證設定

Heresy 這邊很早之前,就有開始使用 WebSocket++ 來開發自己的 WebSocket Server;而後來其實也有改用 Boost.Beast 來做同樣的工作。而這兩套函式庫的底層,其實都是 Boost::asio(官網),所以其實在某些地方還滿接近的。

而之前用起來都還算很正常,不管是老老的 IE 還是 Chrome 都可以使用,在有申請 SSL 憑證的情況下,就算建立加密的 WSS 也是可以正確使用的。

但是,前陣子當想使用 node.js(官網)來進行 WebSocket 的連線的時候,卻發現會出現「unable to verify the first certificate」的錯誤。

閱讀更多»

C++11 的錯誤碼標準 part 3:補充與實作

針對 C++11 提供的 <system_error> 這個函式庫,Heresy 之前已經在 part 1 寫了 error_code 的基本使用,也在 part 2 寫了 error_condition 的東西。而在 part 2 的時候也有提到,由於 Heresy 在寫 part 1 的時候,其實對於 std::error_codestd::error_condtion 的關係有點誤解,導致有一些東西沒講到,所以這邊就先回到 std::error_code 的部分,做一些補充。

首先,之前在實作 error_code 的時候,總共實作了:

  • enum class ErrorCode
  • class ErrorCategory
    • message()
    • name()
  • make_error_code()
  • is_error_code_enum<Heresy::ErrorCode>

閱讀更多»

C++11 的錯誤碼標準 part 2:error_condition

這篇是延續之前的《C++11 的錯誤碼標準:error_code》一文,繼續來講 <system_error> 裡的另一個類別、std::error_condition文件)。

不過老實說,Heresy 在繼續寫這篇的時候,才發現之前對於這邊的設計有些誤解,所以其實在 error_code 這篇文章有的內容可能不夠完整,預計會在用第三篇文章繼續補齊。

error_conditionerror_code 非常地接近,不管是實際儲存的資料,或是介面的設計,基本上都沒有太大的差異;兩者的差別,主要是概念上、使用時機的差別。

兩者的差異,主要是:

  • error_code 基本上是比較底層的錯誤碼,針對有可能會因為作業系統實作的不同
  • error_condition 則是和平台差異無關(platform-independent)的錯誤碼,主要是用來做比較用的

閱讀更多»

C++11 的錯誤碼標準 part 1:error_code

<system_error> 這個函式庫是 C++11 時,加入標準函式庫裡的一個功能(C++ Referencecplusplus),主要是為了在 exception 以外,提供一個更有架構、同時也有擴展能力的錯誤回報機制。

為什麼不都用 exception 呢?主要是因為並不是所有的錯誤都是例外。
像是以網路的程式來說,有一些錯誤狀況,會是有相當高的發生機會、本來就應該要在程式的流程中被考慮到的、而不應該用例外來處理。

所以在這種狀況下,使用 exception 來處理這些錯誤狀況,並不見得是個好的方法。

<system_error> 最初是 Boost C++ Libraries 中的東西(參考),後來才被整合到 C++11 裡的,所以如果有在用 Boost 的話,對他應該不至於太陌生;像是在 Boost::ASIO(參考)裡面,主要就是透過 error_code 來做錯誤的回報。

閱讀更多»

VisualStudio 的視覺化偵錯工具:Graphical Debugging

「Graphical Debugging」(網頁)是 VisualStudio 的一個延伸模組,它的功能是可以把 C++ 與 C# 中特並類型的資料、視覺畫出來、方便在偵錯的時候觀察。官方的說明是:

Visualization of C++ and C# variables during debugging, e.g. Boost.Geometry models, containers of values, arrays of points, etc.

Heresy 最早看到是很久以前的「Boost Debugger visualizers」(網頁),最初應該是只有針對 Boost C++ Libraries 的型別來做監看的修飾,但是看來現在功能多了很多了~

閱讀更多»