[C++ 筆記] 好用的 std::optional

2019-12-22
2 min read

since C++17

std::optional 讓 function 的回傳值多了一個選擇:有值或是 nullopt

例如我們有一個 function 要從某個檔案讀值出來(或是去 DB 查一個東西之類的需求),就假設我們要讀一個 int,我們也許會這樣寫:

int readData(std::string filePath) {
    ...
    int data = readFromFile(...);
    ...

    return data;
}

但如果要讀的檔案不存在呢?這時候要 return 什麼呢?所以這時候我們會改成這樣寫:

bool readData(std::string filePath, int& readData) {
    FILE* file = fopen(...)
    if (!file) {
        return false;
    }

    readData = readFromFile(...);

    return true;
}

我們用一個回傳值代表檔案讀取失敗與否,要是檔案存在且開啟成功,那麼 readData 這個回傳值就代表我們讀到的值。要是回傳值是 false,那 readData 就沒有意義。
但是這樣會讓傳入跟傳出的參數混在一起,第一時間也不容易直覺的分辨出來,像這種情況 Python 就清楚很多:

def readData(filePath):
    data = None
    try:
        with open(filePath, "rb") as f:
           data = f.read(...)
        return data
    except FileNotFoundError as e:
        return None

value = readData("123.txt")
if value:
    pass # Do something...

可以像 Python 那樣都從回傳值來判斷嗎? std::optional 可以達到這個目的:

std::optional<int> readData(std::string filePath) {
    FILE* file = nullptr;
    fopen_s(&file, filePath.c_str(), "rb");
    if (!file) {
        return std::nullopt;
    }

    int readData;
    fread(&readData, 1, sizeof(readData), file);
    fclose(file)

    return readData;
}

auto result = readData("123.txt");
if (result) {
    auto value = result.value();
    // Use value here...
}

// 或是這樣寫也可以
if (result == std::nullopt) {
    // Error handle here
} else {
    auto value = result.value();
    // Use value here...
}

雖然用起來沒辦法讓 C++ 像 Python 那麼簡單,但是 std::optional 確實讓整段 code 看起來更清楚了。
除了 std::optional<T>::value() 以外,還有其他的取值方法:

std::optional<std::string> name;

// Some process...

if (name)
{
    printf("name = %s\n", (*name).c_str());
}

如果 std::optional 包含的是 struct 或是 class,也可以用 -> 來直接存取 member(或 member function):

struct User {
    uint32_t    id;
    std::string name;
    int32_t     age;
};

std::optional<User> user;

// Some process...

if (user) {
    printf("id   = %d\n", user->id);
    printf("name = %s\n", user->name.c_str());
    printf("age  = %d\n", user->age);
}
Avatar

Awin Huang

有物混成,先天地而生,寂兮寥兮,獨立而不改,周行而不殆,可以為天下母。吾不知其名,字之曰道。
comments powered by Disqus