最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C++中std::variant的使用詳解和實(shí)戰(zhàn)代碼示例

 更新時(shí)間:2026年05月19日 09:00:37   作者:點(diǎn)云SLAM  
本文主要介紹了C++中std::variant的使用詳解和實(shí)戰(zhàn)代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

std::variant 是 C++17 引入的一個(gè)類型安全的聯(lián)合體(type-safe union),它可以在多個(gè)類型之間存儲(chǔ)一個(gè)值,并在編譯時(shí)進(jìn)行類型檢查。它是現(xiàn)代 C++ 類型擦除與泛型編程的核心工具之一,適用于構(gòu)建可變類型結(jié)構(gòu)、消息傳遞系統(tǒng)、狀態(tài)機(jī)等。

一、基本概念

#include <variant>

std::variant<T1, T2, ..., Tn> v;
  • 類似于聯(lián)合體 union,但類型安全。
  • std::variant 只能存儲(chǔ)其中一個(gè)類型的值
  • 默認(rèn)構(gòu)造時(shí),會(huì)初始化為第一個(gè)類型的默認(rèn)值

二、核心操作

1. 構(gòu)造與賦值

#include <iostream>
#include <variant>

int main() {
    std::variant<int, std::string> v;

    v = 42;                 // 存儲(chǔ) int
    std::cout << std::get<int>(v) << std::endl;

    v = "hello";            // 存儲(chǔ) string
    std::cout << std::get<std::string>(v) << std::endl;

    return 0;
}

2. 訪問值:std::get<T>()或std::get<index>()

std::get<int>(v);              // 根據(jù)類型訪問
std::get<0>(v);                // 根據(jù)索引訪問(int 是第 0 個(gè)類型)

如果類型不匹配,將拋出 std::bad_variant_access 異常。

3. 判斷當(dāng)前存儲(chǔ)的類型

if (std::holds_alternative<std::string>(v)) {
    std::cout << "v contains a string\n";
}

4. 獲取當(dāng)前類型索引

std::cout << "index = " << v.index() << std::endl;

三、使用std::visit實(shí)現(xiàn)模式匹配

#include <iostream>
#include <variant>

void printVariant(const std::variant<int, std::string>& v) {
    std::visit([](auto&& arg) {
        std::cout << "Value: " << arg << std::endl;
    }, v);
}

四、完整示例:表達(dá)式計(jì)算器

#include <iostream>
#include <variant>
#include <vector>

using Expr = std::variant<int, float, std::string>;

void processExpr(const Expr& e) {
    std::visit([](auto&& val) {
        using T = std::decay_t<decltype(val)>;
        if constexpr (std::is_same_v<T, int>)
            std::cout << "int: " << val << "\n";
        else if constexpr (std::is_same_v<T, float>)
            std::cout << "float: " << val << "\n";
        else if constexpr (std::is_same_v<T, std::string>)
            std::cout << "string: " << val << "\n";
    }, e);
}

int main() {
    std::vector<Expr> exprs = { 1, 3.14f, "hello" };

    for (const auto& e : exprs)
        processExpr(e);

    return 0;
}

五、進(jìn)階用法:遞歸類型(std::monostate+std::unique_ptr)

std::variant 不能直接定義遞歸類型(自身包含自身)。需要使用指針 + std::monostate

struct Node;

using Tree = std::variant<
    std::monostate,        // 空節(jié)點(diǎn)
    int,                   // 葉子
    std::unique_ptr<Node>  // 子樹
>;

struct Node {
    Tree left;
    Tree right;
};

六、注意事項(xiàng)

項(xiàng)目說明
異常std::get<T>(v) 如果類型不對(duì),會(huì)拋出 std::bad_variant_access
默認(rèn)值默認(rèn)初始化為第一個(gè)類型的默認(rèn)構(gòu)造值
索引v.index() 返回當(dāng)前類型在 variant 中的索引
編譯期匹配使用 if constexpr + std::visit 可實(shí)現(xiàn)類型安全分派

七、綜合實(shí)戰(zhàn)示例

下面是一個(gè)用 std::variant 實(shí)現(xiàn)的 有限狀態(tài)機(jī)(FSM)+ 消息分發(fā)系統(tǒng) 的綜合示例,適用于狀態(tài)驅(qū)動(dòng)的系統(tǒng),如游戲角色狀態(tài)、UI 狀態(tài)、網(wǎng)絡(luò)連接狀態(tài)等。

示例目的結(jié)構(gòu)

我們實(shí)現(xiàn)一個(gè)簡(jiǎn)單的 FSM:角色可以在 Idle, Moving, Attacking 三個(gè)狀態(tài)間切換,接收 Message 控制狀態(tài)轉(zhuǎn)換。

1. 基礎(chǔ)定義

#include <iostream>
#include <variant>
#include <string>

// 狀態(tài)定義
struct Idle {};
struct Moving { std::string destination; };
struct Attacking { std::string target; };

// 消息定義
struct StartMoving { std::string destination; };
struct StopMoving {};
struct StartAttack { std::string target; };
struct StopAttack {};

// 狀態(tài)類型和消息類型
using State = std::variant<Idle, Moving, Attacking>;
using Message = std::variant<StartMoving, StopMoving, StartAttack, StopAttack>;

2. 消息處理器(核心)

void handle_message(State& state, const Message& msg) {
    std::visit([&](auto&& current_state) {
        using Current = std::decay_t<decltype(current_state)>;

        std::visit([&](auto&& m) {
            using Msg = std::decay_t<decltype(m)>;

            if constexpr (std::is_same_v<Current, Idle>) {
                if constexpr (std::is_same_v<Msg, StartMoving>) {
                    std::cout << "Idle → Moving to " << m.destination << "\n";
                    state = Moving{m.destination};
                } else if constexpr (std::is_same_v<Msg, StartAttack>) {
                    std::cout << "Idle → Attacking " << m.target << "\n";
                    state = Attacking{m.target};
                }
            } else if constexpr (std::is_same_v<Current, Moving>) {
                if constexpr (std::is_same_v<Msg, StopMoving>) {
                    std::cout << "Moving → Idle\n";
                    state = Idle{};
                } else if constexpr (std::is_same_v<Msg, StartAttack>) {
                    std::cout << "Moving → Attacking " << m.target << "\n";
                    state = Attacking{m.target};
                }
            } else if constexpr (std::is_same_v<Current, Attacking>) {
                if constexpr (std::is_same_v<Msg, StopAttack>) {
                    std::cout << "Attacking → Idle\n";
                    state = Idle{};
                } else if constexpr (std::is_same_v<Msg, StartMoving>) {
                    std::cout << "Attacking → Moving to " << m.destination << "\n";
                    state = Moving{m.destination};
                }
            }
        }, msg);
    }, state);
}

3. 主程序(狀態(tài)切換測(cè)試)

int main() {
    State state = Idle{};

    handle_message(state, StartMoving{"North"});
    handle_message(state, StartAttack{"Dragon"});
    handle_message(state, StopAttack{});
    handle_message(state, StartAttack{"Goblin"});
    handle_message(state, StartMoving{"East"});
    handle_message(state, StopMoving{});

    return 0;
}

輸出示例

Idle → Moving to North
Moving → Attacking Dragon
Attacking → Idle
Idle → Attacking Goblin
Attacking → Moving to East
Moving → Idle

小結(jié):此結(jié)構(gòu)的優(yōu)勢(shì)

特性說明
類型安全std::variant 和 std::visit 編譯期確定類型,無需 RTTI 或類型轉(zhuǎn)換
易擴(kuò)展增加新狀態(tài)或消息只需添加結(jié)構(gòu)體 + 分支處理
面向?qū)ο罂商娲?/td>可替代經(jīng)典面向?qū)ο鬆顟B(tài)機(jī)中的虛函數(shù)分派
適合嵌入式/游戲無動(dòng)態(tài)分配,運(yùn)行時(shí)高效

總結(jié)

用法說明
std::variant<A, B>表示可以存儲(chǔ) A 或 B 類型的變量
std::get<T>(v)獲取當(dāng)前存儲(chǔ)的值(類型匹配)
std::visit()模式匹配:對(duì)當(dāng)前值執(zhí)行對(duì)應(yīng)操作
holds_alternative<T>()判斷當(dāng)前是否存儲(chǔ)的是 T 類型

到此這篇關(guān)于C++中std::variant的使用詳解和實(shí)戰(zhàn)代碼示例的文章就介紹到這了,更多相關(guān)C++ std::variant使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

祁东县| 鄂伦春自治旗| 昔阳县| 保康县| 道孚县| 宜良县| 若羌县| 花莲市| 安西县| 米泉市| 荆门市| 石柱| 巍山| 家居| 铜鼓县| 静安区| 弥渡县| 祁门县| 曲阳县| 左云县| 田东县| 昌吉市| 西和县| 永定县| 孝感市| 汾西县| 四会市| 绥阳县| 司法| 新源县| 呼图壁县| 陆良县| 武功县| 桂林市| 永宁县| 河曲县| 安多县| 哈尔滨市| 太康县| 文成县| 高雄县|