摘要訊息 : C++ 17 引入了帶有初始化的條件陳述式, 進一步避免了名稱污染.

0. 前言

C++ 有不少方式可以避免名稱污染, 比如名稱空間, static 函式或著 static 變數以及函式多載等等. 我們平常編寫程式的時候, 雖然可以使用這些方法去避免名稱污染, 但是有時也會遇到下面這個讓人頭疼的情形 :

#include <algorithm>
#include <vector>

void f(const std::vector<int> &vec, int value) {
    // ...
    const auto iterator {std::find(vec.cbegin(), vec.cend(), value)};
    if(iterator not_eq vec.cend()) {
        // ...
    }
    // ...
}

在函式 f 中, 我們宣告了一個名稱為 iterator 的變數, 它僅僅被用於 if 陳述式的條件判斷上, 接下來就再也沒有程式碼用到它了. 這個時候, 我們不希望 iterator 放在 if 之外, 而是希望把它的可視範圍限制在 if 之內. 很遺憾, C++ 17 之前都無法做到.

為了解決上面這個需求, C++ 17 的提案 P0305R1《Selection statements with initializer》提出了將 iterator 的可視範圍限制在 if 之內的解決方案.

更新紀錄 :

  • 2022 年 4 月 24 日進行第一次更新和修正.

1. 提案內容

C++ 17 允許我們在 if, switchif constexpr 陳述式中宣告變數 :

#include <iostream>

void f(int value) {
    int arr[] {1, 2, 3, 4, 5};
    if(auto it {std::find(begin(arr), end(arr), value)}; it == end(arr)) {
        //do something...
    }
}

enum class status {
    SUCCESSFUL, FAILED, TO_BE_CONTINUED
};

status func();
void func2(status);
constexpr int get_value();

void g() {
    switch(auto status_code {func()}; status_code) {
        case status::SUCCESSFUL :
            func2(status_code);
            break;
        case status::FAILED :
            std::terminate();
        case status::TO_BE_CONTINUED:
            std::clog << "The status is to-be-continued" << std::endl;
            break;
        default:
            break;
    }
    if constexpr(auto value {get_value()}; value > 0) {
        func2(func());
    }
}

現在, 在 if, switch 或者 if constexpr 的作用範圍之外, 已經看不到這些臨時的變數了.