Tag | cxx

  1. std::any 使用方法

    本文要介紹 C++ 17 新增的 std::any 類別。它能儲存所有「可以被複製建構(Copy Constructible)」的數值。以下我們會先介紹 std::any 的基本用法,接著介紹實際的使用情境

    使用方法

    std::any 類別的使用方法分述如下:

    1. 建構物件
    2. 指派運算子
    3. any_cast 函式
    4. has_value 成員函式
    5. reset 成員函式
    6. emplace 成員函式
    7. type 成員函式

    建構物件

    std::any 類別定義於 <any> 標頭檔。以下是幾種建構 std::any 物件的方法:

    #include <any>
    
    int main() {
      std::any …

    More

  2. C++ 執行緒:promise、future、packaged_task 與 async 的使用方法

    今天我想要介紹 C++ 執行緒的高階 API:std::promisestd::futurestd::packaged_taskstd::async。本文的內容可以濃縮為下圖:

    std::future、std::promise、std::packaged_task 與 std::async 的關聯圖

    其中 std::promisestd::future 是執行緒之間的同步通道。std::packaged_task 類別樣版是「函式(Function)」或「函式物件(Function Object)」的轉接器。它會將函式的回傳值包裝為 std::future,讓我們能方便地以 std::thread 執行任何函式。std::async 函式相當於 std::packaged_taskstd::thread 的總和。

    接下來我會分段介紹各個 API:

    1. std …

    More

  3. C++ std::thread join() 與解構函式

    前幾天在除錯的過程中,我注意到程式印出的 Stack Trace 和我的預期相去甚遠。在反覆研究之後,我發現一段有問題的程式碼。大家看得出來有什麼問題嗎?

    thread_bug.cpp:

    extern int subtask1(int x);
    extern int subtask2(int x);
    
    int run(int a, int b) {
      int result1;
      std::thread t([&]() { result1 = subtask1(a); });
    
      int result2 = subtask2(b);
      if (result2 < 0) {
        return -2;
      }
    
      t.join();
      if (result1 < 0) {
        return -1 …

    More

  4. C++ 17 對例外處理規格的改動

    今天我想要介紹 C++ 17 對「例外處理規格(Exception Specification)」的二個改動:

    1. 移除 throw (ClassName)
    2. noexcept 納入型別系統(Type System)

    移除 throw (ClassName) 例外處理規格

    在 C++ 98 我們能為一個函式編寫「例外處理規格」,表明一個函式只會拋出指定例外:

    #include <stdexcept>
    
    void test() throw (std::logic_error, std::runtime_error) {
      // ... some other code ...
    }
    

    以上程式碼裡面的 throw (...) 就是例外處理規格。

    然而除了用以保證不會拋出例外的 throw (),例外處理規格沒有實用價值,因為:

    1. 例外處理規格只會在執行期檢查「有沒有其他例外被拋出」。
    2. 若其他例外被拋出 …

    More

  5. C++ 17 fallthrough、nodiscard、maybe_unused 屬性

    C++ 17 新增三個標準屬性(Attribute):

    本文會依序介紹這三個屬性。

    [[fallthrough]]

    在 C/C++ 語言中,switch 述句通常會有若干個 case 與一個 default。在進入一個 casedefault 之後,如果沒有以 break 述句或其他述句跳出 switch 述句,程式會繼續執行接續的 casedefault

    #include <iostream>
    
    int main() {
      int x = 0;
      std::cin >> x;
    
      int result …

    More

  6. C++ 17 template <auto> 非型別樣版參數型別推導

    在 C++ 17 標準下,我們能以 auto 關鍵字宣告非型別樣版參數(Non-Type Template Argument)。編譯器會以「樣版的實際參數」推導「樣版參數」的型別:

    template <auto Arg>
    struct Example {
      static constexpr auto value = Arg;
    };
    
    enum TestEnum { VAL1, VAL2, };
    
    int main() {
      Example<42> a;    // Arg == 42,   decltype(Arg) == int
      Example<VAL1> b;  // Arg == VAL1, decltype(Arg) == TestEnum
    }
    

    本文會先介紹 template <auto …

    More

  7. C++ 17 __has_include 前置處理表達式

    __has_include 是 C++ 17 加進前置處理器(Preprocessor)的新功能。我們能以 __has_include 表達式偵測某個標頭檔(Header File)是否存在。如果前置處理器能找到指定的標頭檔,__has_include 表達式的計算結果會是 1;反之,其計算結果會是 0。例如:

    example.cpp:

    #if __has_include("example.h")
    #include "example.h"
    #else
    #error "cannot find example.h"
    #endif
    
    int main() {}
    

    因為我們沒有建立 example.h,所以前置處理器在計算 #if 前置處理指令的時候,會將 __has_include("example.h") 表達式視為 …

    More

  8. C++ 17 Inline Variable

    Inline Variable(內嵌變數)是 C++ 17 新增的功能。Inline Variable 與 Inline Function(內嵌函式)相似,能讓我們在多個 Translation Unit(編譯單元)定義同樣的變數[1]。鏈結器(Linker)在處理多個 Object File(目的檔)的時候會再將名字相同的 Inline Variable 合併為一個變數。

    本文大綱:

    1. 動機 -- 介紹 C++ 標準新增 Inline Variable 的動機。
    2. Inline Variable -- 介紹 Inline Variable 的語法與注意事項。
    3. 替代方案 -- 介紹 C++ 17 以前 Inline …

    More

  9. C++ 17 constexpr 與 Lambda 表達式

    C++ 17 將 Lambda Expression 納入常數表達式(constexpr)的範疇,所以我們也能在只接受編譯期常數的地方呼叫 Lambda Expression 定義的 Lambda Function:

    void test() {
      auto f = [](int a, int b) constexpr {
        return a + b;
      };
      static_assert(f(1, 2) == 3, "");
    }
    

    本文會先回顧 C++ 11C++ 14 標準定義的 constexpr 再介紹 C++ 17 的改進。

    C++ 11 constexpr

    C++ 11 首次引入常數表達式 …

    More

  10. C++ 17 在 Lambda Expression 捕捉 *this

    如果一個成員函式(Member Function)有 Lambda Expression 而且該 Lambda Expression 有指定預設補捉模式(不論是傳值或傳參考)。當 Lambda Expression 內有程式碼指稱「成員函式」或「資料成員」時,this 會被隱含地加入 Capture List。Lambda Expression 在執行時會透過 this 指標存取成員函式或資料成員:

    #include <cassert>
    
    class Example {
    private:
      int value_;
    public:
      Example(int value = 0) : value_(value) {}
    
      void run() {
        auto f = [&]() { ++value_; };
        auto g = [=]() { ++value_ …

    More

Page 1 / 2 Next »