C++23:最新特性

C++23 是当前已发布的最新标准,继续完善和扩展 C++ 的功能。

Deducing this(推导 this)

struct Widget {
    void process(this auto&& self) {
        // self 可以是左值引用、右值引用或 const 引用
        self.doSomething();
    }

    void doSomething() & {
        std::cout << "Lvalue\n";
    }

    void doSomething() && {
        std::cout << "Rvalue\n";
    }
};

Widget w;
w.process();        // Lvalue
Widget{}.process(); // Rvalue

if consteval

constexpr int compute(int x) {
    if consteval {
        // 编译期执行的代码
        return x * 2;
    } else {
        // 运行期执行的代码
        return x * 3;
    }
}

constexpr int result = compute(5);  // 10 (编译期)
int runtime = compute(5);  // 15 (运行期)

auto(x) 和 auto{x}

std::vector<int> vec = {1, 2, 3};

// 强制拷贝
auto copy = auto(vec);  // vec 的副本

// 强制移动
auto moved = auto(std::move(vec));  // 移动构造

// 括号形式
auto copy2 = auto{vec};

静态运算符(Static Operators)

struct Number {
    int value;

    static Number operator+(Number a, Number b) {
        return Number{a.value + b.value};
    }

    static Number operator-(Number a, Number b) {
        return Number{a.value - b.value};
    }
};

Number n1{1};
Number n2{2};
Number n3 = n1 + n2;  // Number{3}
Number n4 = n1 - n2;  // Number{-1}

多维 operator[]

// C++23 之前
data[0][1][2];

// C++23:支持多维 operator[]
template<typename T>
class Tensor3D {
    T* data_;
    std::size_t dim1_, dim2_, dim3_;

public:
    Tensor3D(T* data, std::size_t d1, std::size_t d2, std::size_t d3)
        : data_(data), dim1_(d1), dim2_(d2), dim3_(d3) {}

    // C++23 多维 operator[]
    auto operator[](std::size_t i) requires std::is_array_v<T> {
        return std::mdspan(data_ + i * dim2_ * dim3_, dim2_, dim3_);
    }
};

[[assume]] 属性

int divide(int a, int b) {
    [[assume(b != 0)]];  // 告诉编译器 b 不为 0
    return a / b;
}

int process(int value) {
    if (value < 0 || value > 100) [[assume(false)]];
    // 编译器知道 value 在 [0, 100] 范围内
    return value * 2;
}

size_t 字面量后缀

// C++23 字面量后缀
using namespace std::literals;

std::size_t a = 123uz;  // size_t
std::size_t b = 0uz;    // 空指针安全的 size_t

// 与 sizeof 配合
auto size = sizeof(int)uz;

std::print 和 std::println

#include <print>

std::print("Hello, World!\n");
std::println("Hello, World!");  // 自动换行

// 格式化
std::println("Name: {}, Age: {}", "Alice", 30);

// 支持容器
std::vector<int> vec = {1, 2, 3};
std::println("Vector: {}", vec);  // Vector: [1, 2, 3]

// 支持格式化选项
std::println("Pi: {:.2f}", 3.14159);  // Pi: 3.14
std::println("Binary: {:b}", 42);     // Binary: 101010

// 输出到文件
std::println(stdout, "To stdout");

标准库模块

// 导入标准库模块而不是头文件
import std;

// 不再需要 #include <iostream>, <vector>, 等
int main() {
    std::println("Hello, World!");
    std::vector<int> vec = {1, 2, 3};
    return 0;
}

std::expected

#include <expected>

std::expected<int, std::string> divide(int a, int b) {
    if (b == 0) {
        return std::unexpected("Division by zero");
    }
    return a / b;
}

auto result = divide(10, 2);
if (result) {
    std::println("Result: {}", *result);
} else {
    std::println("Error: {}", result.error());
}

// 使用 value_or
int value = divide(10, 0).value_or(-1);

// 链式操作
auto final = divide(10, 2).transform([](int x) { return x * 2; });

std::generator

#include <generator>

std::generator<int> range(int start, int end) {
    for (int i = start; i < end; ++i) {
        co_yield i;
    }
}

for (auto x : range(1, 5)) {
    std::println("{}", x);  // 1 2 3 4
}

// 生成器组合
std::generator<int> fibonacci() {
    int a = 0, b = 1;
    while (true) {
        co_yield a;
        auto next = a + b;
        a = b;
        b = next;
    }
}

std::mdspan

#include <mdspan>

int data[12] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};

// 3x4 矩阵视图
std::mdspan<int, std::extents<std::size_t, 3, 4>> mat(data);

std::println("mat[1][2] = {}", mat[1][2]);  // 7

// 动态维度
std::mdspan<int, std::dextents<std::size_t, 2>> dyn(data, 3, 4);

// 切片视图
std::mdspan row = std::submdspan(mat, std::slice{1, 1, 2});  // 第一行的一部分

std::flat_map 和 std::flat_set

#include <flat_map>
#include <flat_set>

// 扁平化容器,使用排序的 vector 存储
std::flat_map<std::string, int> map;
map["a"] = 1;
map["b"] = 2;

// 保持排序
map.sort();  // 按键排序

// 快速查找
if (map.contains("a")) {
    auto it = map.find("a");
}

std::flat_set<int> set = {3, 1, 4, 1, 5};  // 自动去重和排序

// 范围操作
auto range = map.equal_range("b");

std::byteswap

#include <bit>

uint32_t x = 0x12345678;
uint32_t y = std::byteswap(x);  // 0x78563412

// 大小端转换
uint16_t a = 0xABCD;
uint16_t swapped = std::byteswap(a);  // 0xCDAB

std::to_underlying

#include <type_traits>

enum class Color : int { Red = 1, Green = 2, Blue = 3 };

Color c = Color::Red;
int value = std::to_underlying(c);  // 1

// 强转等价但更清晰
auto val = std::to_underlying(Color::Green);  // 2

std::string::contains

std::string str = "Hello, World!";

// C++23 之前
if (str.find("World") != std::string::npos) { /* ... */ }

// C++23
if (str.contains("World")) { /* ... */ }
if (str.contains('o')) { /* ... */ }

// string_view 也有 contains
std::string_view sv = "test.txt";
if (sv.contains("test")) { /* ... */ }

std::unreachable

#include <utility>

int process(int value) {
    switch (value) {
        case 1:
            return 10;
        case 2:
            return 20;
        default:
            std::unreachable();  // 告诉编译器这里不可达
    }
}

void* allocate(std::size_t size) {
    if (size == 0) {
        return nullptr;
    }
    // 编译器知道 size > 0
    std::unreachable();
}

常用特性总结

最常用的 C++23 特性:

  • std::printstd::println
  • std::expected
  • std::generator
  • std::flat_mapstd::flat_set
  • 标准库模块(import std
  • std::byteswap
  • std::string::contains