摘要訊息 : 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
, switch
和 if 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
的作用範圍之外, 已經看不到這些臨時的變數了.
自創文章, 原著 : Jonny. 如若閣下需要轉發, 在已經授權的情況下請註明本文出處 :