std::visit
通常與前文的Petty C++ - std::variant
一起使用,是 C++ 17 引入的用於處理std::variant
中的數據,並執行相應的操作。
基本使用#
std::visit
需要兩個主要參數
-
visitor:是一個可調用對象(lambda 函數對象),用於處理 variant 中的數據
-
variants:一個或多個
std::variant
實例
示例#
int main() {
// 創建一個 std::variant,它可以存儲 int 或 std::string
std::variant<int, std::string> var;
// 將一個 int 值存入 variant
var = 42;
// 使用 std::visit 來處理 variant 中的值
std::visit([](auto&& arg) {
std::cout << "Value: " << arg << std::endl;
}, var);
// 將一個 std::string 值存入 variant
var = std::string("Hello, world!");
// 再次使用 std::visit 來處理新的值
std::visit([](auto&& arg) {
std::cout << "Value: " << arg << std::endl;
}, var);
return 0;
}
多個 variant#
處理多個 variant 時,需要 visitor 能夠處理所有可能出現的類型,如果不在 visitor 中對不同類型的組合進行分支處理,visitor 會為每一種可能的類型組合生成不同的函數調用邏輯。如果有多個 variant,每個 variant 包含多種類型,可能的類型組合呈指數增長。
為了避免這種情況,可以使用如下方法節省開銷:
- 減少 variant 的類型數量
- 使用
std::monostate
// todo - 使用分支
- 使用多態
template<typename T>
void process(const T& value) {
if constexpr (std::is_same_v<T, int>) {
std::cout << "Processing int: " << value << std::endl;
} else if constexpr (std::is_same_v<T, std::string>) {
std::cout << "Processing string: " << value << std::endl;
} else {
std::cout << "Processing other type" << std::endl;
}
}
通過 if constexpr 和模板類型推導,編譯器只會為常見的類型生成特定的邏輯,而通用處理則減少了不必要的代碼生成。