處理「多條件組合」時,傳統做法常用 `int` 掩碼配合 `if-else` 鏈,條件一多代碼即變得冗長難維護。STL `std::bitset` 以編譯期固定大小的位陣列,提供直觀的「置位/測試/翻轉」語義,讓組合邏輯清晰且高效。
需求:滑鼠點選時,同時在點陣列與線陣列中尋找距離最近且小於閾值的對象,產生四種組合情況:
UINT flag = 0;
if (hitPoint && !hitLine) flag = 1;
else if (!hitPoint && hitLine) flag = 2;
else if (hitPoint && hitLine) flag = 3;
// 後續仍需 switch(flag) 處理,易漏情況、難擴展
#include <bitset>
#include <vector>
struct Point { double x, y; };
struct Line { Point p1, p2; };
std::bitset<2> hitMask; // bit0:點 bit1:線
// 獨立判斷,互不干擾
if (findNearestPoint(mousePos, points, threshold)) hitMask.set(0);
if (findNearestLine (mousePos, lines, threshold)) hitMask.set(1);
// 後續處理:語義清晰
if (hitMask.none()) {
// 情況 1:都沒命中
} else if (hitMask.test(0) && !hitMask.test(1)) {
// 情況 2:僅點
} else if (!hitMask.test(0) && hitMask.test(1)) {
// 情況 3:僅線
} else { // hitMask == 0b11
// 情況 4:都命中 → 比較距離
double dPt = distToPoint(mousePos, nearestPoint);
double dLn = distToLine (mousePos, nearestLine);
// 取較近者...
}
| 操作 | 語法 | 說明 |
|---|---|---|
| 置位 | `bs.set(pos)` / `bs.set()` | 單位/全置 1 |
| 復位 | `bs.reset(pos)` / `bs.reset()` | 單位/全置 0 |
| 翻轉 | `bs.flip(pos)` / `bs.flip()` | 單位/全取反 |
| 測試 | `bs.test(pos)` | 返回 bool,越界拋出 `out_of_range` |
| 任意/全為/全非 | `bs.any()` / `bs.all()` / `bs.none()` | 快速判斷整體狀態 |
| 計數 | `bs.count()` | 返回 1 的個數 |
| 轉字串 | `bs.to_string()` | 高位在前,如 "0011" |
| 轉整數 | `bs.to_ulong()` / `to_ullong()` | 位數 ≤ 64 時可用 |
| 位運算 | `&` `|` `^` `~` `<<` `>>` | 支援標準位運算子 |
MFC `OnMouseMove(UINT nFlags, CPoint)` 中 `nFlags` 即為位掩碼(`MK_LBUTTON`、`MK_CONTROL` 等)。若自行設計訊息系統,可用 `bitset<32>` 替代,獲得型別安全與可讀性:
enum MouseFlag { LBUTTON=0, RBUTTON=1, SHIFT=2, CTRL=3, MIDDLE=4 };
std::bitset<32> flags;
flags.set(LBUTTON); // 清楚表達意圖
if (flags.test(CTRL) && flags.test(LBUTTON)) { /* Ctrl+左鍵 */ }