🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

前言

C++每三年會制定新的標準,截至2025年11月,最新的C++23正在各大編譯器中實作中。
而下一個標準的C++26也在標準化委員會中進行制定。
此次將介紹C++23新增的功能以及C++26中提議的功能,並附上程式碼範例,總結C++的最新動向。

※本文章基於公開的標準化文件和cppreference,從一般開發者的角度進行整理。

1. C++標準的進化時間表

C++由ISO每三年週期更新。最新版本為C++23,下一個版本為C++26,但在實際開發現場,C++17和C++20仍然是主流。不同版本間可以使用的功能差異很大,因此了解哪些標準新增了什麼功能十分重要。

當前的C++生態系統

C++生態系統
出典: ISO C++ Standards Committee
上圖顯示了從C++98到未來C++29的標準化流向。藍色條代表正式標準規範,綠色條則是以技術規範(TS)並行開發的功能群。

特別注意的點

  • 每三年更新一次的標準(自C++11以來)
  • 大型功能作為TS進行單獨開發,然後整合入本體
  • Modules、Coroutines、Ranges等從TS移至標準的實例

編譯器支援狀況

【主要編譯器概要】

  • GCC - GNU Compiler Collection,Linux/Unix系的標準
  • Clang - LLVM系,macOS標準,優秀的錯誤信息
  • MSVC - Microsoft Visual C++,Windows/Visual Studio標準
編譯器 C++20 C++23 C++26(實驗性)
GCC 14.2 ✅ 完全 ✅ 幾乎實作完成 -std=c++2c 可試用部分功能
Clang 18 ✅ 完全 ✅ 主要功能已支援 僅試作靜態反射、模式匹配等部分功能
MSVC 17.11 ✅ 幾乎完全 🔶 語言和STL皆在支持中 ❌ 無官方支援(擴展功能水平有限)

※截至2025年11月的資訊。
※詳細的功能別支援狀況可參考 cppreference

2. C++23的實用新功能

C++23雖然不是大規模的變更,但添加了許多日常生活中非常有用的功能。此處從易於使用的新增功能開始介紹。

2.1 std::expected - 錯誤處理革命

實現了類似Rust風格的錯誤處理,不再需要使用例外。

#include <expected>
#include <string>
#include <iostream>
#include <fstream>
#include <filesystem>

// 讀取檔案的函數範例
std::expected<std::string, std::string> read_config(const std::string& path) {
    if (path.empty()) {
        return std::unexpected{"路徑為空"};
    }

    if (!std::filesystem::exists(path)) {
        return std::unexpected{"檔案不存在: " + path};
    }

    // 實際的讀取處理
    std::ifstream file(path);
    if (!file) {
        return std::unexpected{"無法打開檔案"};
    }

    std::string content((std::istreambuf_iterator<char>(file)),
                        std::istreambuf_iterator<char>());
    return content;
}

// 使用範例
int main() {
    auto result = read_config("config.json");

    if (result) {
        std::println("設定內容: {}", *result);
    } else {
        std::println("錯誤: {}", result.error());
    }

    // 方法鏈的使用
    auto processed = read_config("data.json")
        .transform([](const std::string& s) { return s.size(); })
        .value_or(0);
}

傳統函數需要拋出例外或以返回值方式傳遞錯誤碼。std::expected是一種表示“成功值或錯誤值”的類型,特別在禁止使用例外的嵌入式和遊戲開發中非常受用。

2.2 std::print / std::println - 型別安全的輸出

終於可以告別printf了!

#include <print>
#include <vector>
#include <chrono>
#include <format>

struct Point {
    double x, y;
};

// 自定義型別的格式化
template<>
struct std::formatter<Point> : std::formatter<std::string> {
    auto format(const Point& p, format_context& ctx) const {
        return std::formatter<std::string>::format(
            std::format("({:.2f}, {:.2f})", p.x, p.y), ctx);
    }
};

int main() {
    // 基本用法
    std::println("你好, {}!", "世界");

    // 結合多種型別
    std::println("整數: {}, 浮點數: {:.2f}, 字串: {}", 
                 42, 3.14159, "test");

    // 容器的輸出
    std::vector<int> vec = {1, 2, 3, 4, 5};
    std::println("向量: {}", vec);

    // 自定義型別
    Point p{3.14, 2.71};
    std::println("座標: {}", p);

    // 輸出時間
    auto now = std::chrono::system_clock::now();
    std::println("當前時間: {:%Y-%m-%d %H:%M:%S}", now);
}

新增了可直接格式化並輸出到標準輸出的函數。因為編譯時進行型別檢查,可以避免printf中格式字串與實際參數不匹配而導致的錯誤。

2.3 deducing this - 簡化方法鏈

CRTP(Curiously Recurring Template Pattern)不再需要。

class Builder {
private:
    std::string result_;

public:
    // 傳統的方法(C++20之前)
    // Builder& add_old(const std::string& s) & { 
    //     result_ += s; 
    //     return *this; 
    // }
    // Builder&& add_old(const std::string& s) && { 
    //     result_ += s; 
    //     return std::move(*this); 
    // }

    // C++23: 使用deducing this整合為一個函數
    template<class Self>
    auto&& add(this Self&& self, const std::string& s) {
        self.result_ += s;
        return std::forward<Self>(self);
    }

    std::string build() const { return result_; }
};

// 使用範例
auto result = Builder{}
    .add("你好")
    .add(" ")
    .add("世界")
    .build();  // "你好 世界"

在類的成員函數中,可以透過模板取得this的型別。這樣會使得返還成員函數鏈的程式碼變得更加簡單。

2.4 std::mdspan - 多維陣列視圖

支持在科學計算和遊戲開發中經常使用的矩陣運算。

#include <mdspan>
#include <vector>

void process_matrix() {
    // 將一維陣列視為二維
    std::vector<float> data(100 * 200);

    // 解析為100x200的矩陣
    std::mdspan<float, std::extents<size_t, 100, 200>> matrix(data.data());

    // 二維訪問
    for (size_t i = 0; i < matrix.extent(0); ++i) {
        for (size_t j = 0; j < matrix.extent(1); ++j) {
            matrix(i, j) = i * j;  // C++23的多維下標
        }
    }

    // 動態大小的情況
    std::mdspan<float, std::dextents<size_t, 2>> dynamic_matrix(
        data.data(), 100, 200);
}

新增了便於進行科學計算和遊戲開發的多維陣列訪問。能夠將一維陣列作為多維陣列使用,從而實現針對內存佈局的高效處理。

3. C++26的革新功能(預覽)

C++26正在研究一系列旨在使現有C++更加現代化和自動化的方式。尤其受到矚目的是將大幅簡化元編程的功能群。

※注意:本章中介紹的C++26功能仍在提議和審議中,規範、語法和名稱可能會在未來的WG21會議中變更。

3.1 靜態反射 - 元編程的新時代

從代碼中獲取型別信息,並能以元方式處理程序結構的功能。這將使JSON序列化的自動生成、enum到字串的轉換以及大量模板代碼的自動化成為可能。

// C++26提案(語法可能會變更)
template<typename T>
void serialize_to_json(const T& obj) {
    std::print("{{");
    bool first = true;

    for (...) {
        if (!first) std::print(", ");
        first = false;

        std::print("\"{}\": ", member.name());
        serialize_value(obj.*member.pointer());
    }

    std::print("}}");
}

struct Person {
    std::string name;
    int age;
    double height;
};

// 自動轉為JSON
Person p{"Alice", 30, 165.5};
serialize_to_json(p);  // {"name": "Alice", "age": 30, "height": 165.5}

3.2 模式匹配 - 更具表達力的分支

擴展switch語句,能包含結構體的解構與條件語句的描述。函數式語言中常見的功能最終也導入到C++。

// C++26提案
std::variant<int, double, std::string> value = 42;

inspect(value) {
    <int> i => std::println("整數: {}", i);
    <double> d if (d > 0) => std::println("正數: {}", d);
    <std::string> s => std::println("字串: {}", s);
    _ => std::println("其它");
}

// 與結構化綁定的結合
struct Point { int x, y; };
std::optional<Point> maybe_point = Point{10, 20};

inspect(maybe_point) {
    <std::nullopt> => std::println("無");
    <Point{.x = 0, .y = 0}> => std::println("原點");
    <Point{.x = x, .y = y}> if (x == y) => std::println("對角線: {}", x);
    <Point{.x = x, .y = y}> => std::println("點: ({}, {})", x, y);
}

3.3 std::embed - 編譯時資源嵌入

將資源檔案(圖片、HTML等)嵌入到源代碼中的功能。無需在編譯後隨附檔案,使配發更加簡單。

// C++26提案
#include <embed>

// 嵌入著色器代碼
constexpr std::span<const std::byte> shader = 
    std::embed("shaders/vertex.glsl");

// 嵌入HTML模板
constexpr std::string_view html_template = 
    std::embed_string("templates/index.html");

// 嵌入二進制數據
constexpr auto icon_data = std::embed("assets/icon.png");

4. C++與Rust/Carbon的共存策略

在系統編程領域,許多強調內存安全性的 Rust 和 Google為了C++代碼庫的遷移而開發的 Carbon 等新選擇正逐漸出現。
但實際上,眾多既有的C++資產和新語言間的共存正在逐漸形成。

Rust擁有獨特的設計理念,而Carbon則明確提供C++的遷移路徑,這是二者的不同點。

【現實的使用分配】

// C++側的接口
extern "C" {
    // Rust可調用的函數
    void process_data(const uint8_t* data, size_t len);
}

// 呼叫Rust側的高速處理
extern "C" {
    void rust_parallel_compute(float* array, size_t size);
}

class HybridProcessor {
    std::vector<float> data_;

public:
    void compute() {
        // 現存的C++代碼
        prepare_data();

        // 性能關鍵部分由Rust處理
        rust_parallel_compute(data_.data(), data_.size());

        // 結果的後處理在C++中進行
        postprocess();
    }
};

【遷移策略的實例】

專案類型 推薦方法
新建Web服務 優先考慮Rust
現有遊戲引擎 繼續使用C++ + 部分使用Rust
嵌入式系統 C++(重視實時性)
系統工具 考慮Go/Rust

5. 實踐C++23/26導入指南

要使用C++23的功能,只需在編譯器和CMake中指定標準版本即可。
先前需要使用 -fcoroutines 等實驗性標誌,但自 C++20以後不再需要

<details><summary>查看範例</summary>

cmake_minimum_required(VERSION 3.25)
project(ModernCppExample LANGUAGES CXX)

# ---- 明確指定C++23(禁用擴展)----
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# ---- 稍微提高警告級別(防止現場事故)----
if(MSVC)
  add_compile_options(/W4 /permissive-)
else()
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# ---- (可選)需在Clang + 非Apple Unix中使用libc++ ----
option(USE_LIBCXX "在非Apple Unix中使用Clang的libc++" OFF)
if(USE_LIBCXX AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT APPLE AND NOT WIN32)
  add_compile_options(-stdlib=libc++)
  add_link_options(-stdlib=libc++)
endif()

# ---- (可選)使用C++26預覽特性(提議階段,規範變更風險)----
option(EXPERIMENTAL_CPP26 "啟用C++26預覽特性" OFF)
if(EXPERIMENTAL_CPP26)
  if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    # GCC/Clang用預覽功能,添加 -std=c++2c
    add_compile_options(-std=c++2c)
    add_compile_definitions(CPP26_PREVIEW)
  elseif(MSVC)
    # MSVC對C++26的預覽支援尚不完善,須小心
    message(WARNING "MSVC的C++26預覽支援尚不完善,/std:c++latest下可部分測試,請自擔風險。")
    # add_compile_options(/std:c++latest)  # ←如需使用,請自行決定開啟
    add_compile_definitions(CPP26_PREVIEW)
  endif()
endif()

# ---- 生成執行檔(樣本)----
# 請在現有專案中用自己的目標替換
add_executable(app
  src/main.cpp
)

# ---- 參考備註(舊標誌已不再需要/不推薦)----
# -fcoroutines / -fcoroutines-ts : 自C++20以後不再需要(已標準化)
# -fmodules-ts                  : 用於Modules TS。目前的導入應考慮各個編譯器的方案及
#                                 CMake的 FILE_SET(cxx_modules)(不要輕易添加TS標誌)
# -stdlib=libc++                : 僅在Clang + 某些Unix中使用libc++的情況(由上方選項控制)

</details>

總結

C++是 謹慎且穩步發展的基礎技術。此次總結了C++的最新動向。

重點

  • C++23已進入實用階段,可以使用std::expectedstd::print等功能。
  • C++26計劃引入反射與模式匹配等革新功能。
  • Rust和Carbon與其「取代」的關係,更是「共存與補充」。
  • 結合大量既有的C++資產與新功能,使現代開發成為可能。

※本文章資訊截至2025年11月整理而成。


原文出處:https://qiita.com/Sakai_path/items/24537a84c2437e9e527f


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝14   💬4   ❤️5
465
🥈
我愛JS
📝1   💬4   ❤️2
48
🥉
酷豪
1
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付