S SmartDocs
Série: C++ cpp 197 linhas · Atualizado 2026-04-03

structured_bindings.cpp

C++/Part4_現代CPP/Ch20_CPP17特性精選/structured_bindings.cpp

// Ch20 範例:結構化綁定(Structured Bindings)
// 編譯:g++ -std=c++17 -Wall -o structured_bindings structured_bindings.cpp

#include <iostream>
#include <string>
#include <tuple>
#include <map>
#include <unordered_map>
#include <vector>
#include <utility>
#include <cstdlib>

// ============================================================
// 輔助函式與結構體
// ============================================================

struct Point3D {
    double x, y, z;
};

struct Student {
    std::string name;
    int age;
    double gpa;
};

// 回傳多個值的函式
std::tuple<bool, std::string, int> processRequest(int id) {
    if (id > 0) {
        return {true, "處理成功", 0};
    } else {
        return {false, "無效的 ID", -1};
    }
}

// 回傳 pair 的函式(模擬查詢操作)
std::pair<bool, double> safeDivide(double a, double b) {
    if (b == 0.0) {
        return {false, 0.0};
    }
    return {true, a / b};
}

// ============================================================
// 主程式
// ============================================================
int main() {
    std::cout << std::string(60, '=') << "\n";
    std::cout << "C++17 結構化綁定(Structured Bindings)完整範例\n";
    std::cout << std::string(60, '=') << "\n\n";

    // --- 1. 搭配 std::pair ---
    std::cout << "【1. 搭配 std::pair】\n";
    std::cout << std::string(50, '-') << "\n";

    auto [success, value] = safeDivide(10.0, 3.0);
    std::cout << "10 / 3 → 成功:" << std::boolalpha << success
              << ",結果:" << value << "\n";

    auto [ok, val] = safeDivide(10.0, 0.0);
    std::cout << "10 / 0 → 成功:" << ok
              << ",結果:" << val << "\n";

    // std::div 回傳 div_t(含 quot 和 rem)
    auto [quotient, remainder] = std::div(17, 5);
    std::cout << "17 ÷ 5 = " << quotient << " 餘 " << remainder << "\n\n";

    // --- 2. 搭配 std::tuple ---
    std::cout << "【2. 搭配 std::tuple】\n";
    std::cout << std::string(50, '-') << "\n";

    auto [reqSuccess, message, errorCode] = processRequest(42);
    std::cout << "請求 42 → 成功:" << reqSuccess
              << ",訊息:" << message
              << ",錯誤碼:" << errorCode << "\n";

    auto [reqOk, msg, err] = processRequest(-1);
    std::cout << "請求 -1 → 成功:" << reqOk
              << ",訊息:" << msg
              << ",錯誤碼:" << err << "\n";

    // 直接解構 make_tuple
    auto [name, age, score] = std::make_tuple(std::string("Alice"), 20, 95.5);
    std::cout << "姓名:" << name << ",年齡:" << age
              << ",分數:" << score << "\n\n";

    // --- 3. 搭配 struct ---
    std::cout << "【3. 搭配 struct】\n";
    std::cout << std::string(50, '-') << "\n";

    Point3D p{1.5, 2.7, 3.9};
    auto [x, y, z] = p;  // 拷貝
    std::cout << "Point3D: (" << x << ", " << y << ", " << z << ")\n";

    Student s{"Bob", 21, 3.85};
    const auto& [sName, sAge, sGpa] = s;  // 唯讀參考,不拷貝
    std::cout << "學生:" << sName << ",年齡:" << sAge
              << ",GPA:" << sGpa << "\n";

    // 使用參考修改原始值
    Student s2{"Charlie", 22, 3.5};
    auto& [n2, a2, g2] = s2;
    g2 = 3.9;  // 透過綁定修改原始結構
    std::cout << "修改後的 GPA:" << s2.gpa << "\n\n";

    // --- 4. 搭配 std::map 迴圈 ---
    std::cout << "【4. 搭配 std::map 迴圈】\n";
    std::cout << std::string(50, '-') << "\n";

    std::map<std::string, int> examScores = {
        {"Alice", 95}, {"Bob", 87}, {"Charlie", 92},
        {"Diana", 98}, {"Eve", 76}
    };

    std::cout << "考試成績:\n";
    for (const auto& [studentName, studentScore] : examScores) {
        std::cout << "  " << studentName << ": " << studentScore;
        if (studentScore >= 90) std::cout << " ★";
        std::cout << "\n";
    }
    std::cout << "\n";

    // 搭配 unordered_map
    std::unordered_map<std::string, std::string> capitals = {
        {"台灣", "台北"}, {"日本", "東京"},
        {"法國", "巴黎"}, {"德國", "柏林"}
    };

    std::cout << "各國首都:\n";
    for (const auto& [country, capital] : capitals) {
        std::cout << "  " << country << " → " << capital << "\n";
    }
    std::cout << "\n";

    // --- 5. 搭配 map::insert 的結果 ---
    std::cout << "【5. 搭配 insert 回傳值】\n";
    std::cout << std::string(50, '-') << "\n";

    std::map<std::string, int> inventory;

    // insert 回傳 pair<iterator, bool>
    auto [it1, inserted1] = inventory.insert({"蘋果", 50});
    std::cout << "插入「蘋果」→ "
              << (inserted1 ? "成功" : "已存在")
              << ",數量:" << it1->second << "\n";

    auto [it2, inserted2] = inventory.insert({"蘋果", 100});
    std::cout << "再插入「蘋果」→ "
              << (inserted2 ? "成功" : "已存在")
              << ",數量:" << it2->second << "\n\n";

    // --- 6. 搭配陣列 ---
    std::cout << "【6. 搭配陣列】\n";
    std::cout << std::string(50, '-') << "\n";

    int rgb[] = {255, 128, 0};
    auto [r, g, b] = rgb;
    std::cout << "RGB 顏色:(" << r << ", " << g << ", " << b << ")\n";

    double coords[] = {3.14, 2.72};
    auto [cx, cy] = coords;
    std::cout << "座標:(" << cx << ", " << cy << ")\n\n";

    // --- 7. 實際應用:批次處理結果 ---
    std::cout << "【7. 實際應用:批次處理結果】\n";
    std::cout << std::string(50, '-') << "\n";

    std::vector<std::pair<std::string, double>> transactions = {
        {"購買原料", -1500.0},
        {"銷售收入", 3200.0},
        {"水電費", -800.0},
        {"利息收入", 150.0},
        {"設備維護", -450.0}
    };

    double totalIncome = 0.0, totalExpense = 0.0;
    for (const auto& [desc, amount] : transactions) {
        std::cout << "  " << desc << ": " << amount << "\n";
        if (amount > 0) totalIncome += amount;
        else totalExpense += amount;
    }
    std::cout << "  ────────────────────────\n";
    std::cout << "  總收入:" << totalIncome << "\n";
    std::cout << "  總支出:" << totalExpense << "\n";
    std::cout << "  淨利:" << totalIncome + totalExpense << "\n\n";

    // --- 總結 ---
    std::cout << std::string(60, '=') << "\n";
    std::cout << "結構化綁定讓解構多值回傳更簡潔,適用於:\n";
    std::cout << "  • std::pair / std::tuple\n";
    std::cout << "  • struct(公開成員)\n";
    std::cout << "  • 固定大小陣列\n";
    std::cout << "  • map/unordered_map 的 range-based for\n";
    std::cout << "  • insert/emplace 等回傳 pair 的操作\n";

    return 0;
}

Artigos relacionados