C++26 新特性预览(Preview)

文章目录

    • 1. 静态反射 (Static Reflection)
      • 示例: 枚举转字符串
      • 应用场景
    • 2. 合约 (Contracts)
      • 示例: 定义函数合约
      • 应用场景
    • 3. 条件中的结构化绑定 (Structured Bindings in Conditions)
      • 示例: 改进的错误处理
      • 应用场景
    • 4. 包索引 (Pack Indexing)
      • 示例: 获取参数包的第一个和最后一个元素
      • 应用场景
    • 5. 饱和算术 (Saturation Arithmetic)
      • 示例: 安全算术操作
      • 应用场景
    • 6. 为函数`delete`标记添加说明
      • 应用场景
    • 7. 匿名占位符的改进
    • 8. 用户自定义 `static_assert` 错误信息
    • 9. 为花括号初始化的内容提供静态存储支持
    • 10. 新的头文件`<debugging>`
    • 总结

C++26 引入了一系列新功能, 进一步提升了语言的灵活性, 性能和易用性. 本文将列举其中的一些新特性, 并通过代码示例帮助您快速掌握.


1. 静态反射 (Static Reflection)

静态反射允许开发者在编译时查询和操作类型信息, 为元编程提供了强大的支持. 这一特性极大地简化了类型处理, 自动生成代码等复杂任务.

示例: 枚举转字符串

#include <experimental/meta>
#include <iostream>
#include <string>
#include <type_traits>

template <typename E>
    requires std::is_enum_v<E>
constexpr std::string enum_to_string(E value) {
    std::string result = "<unnamed>";
    [:expand(std::meta::enumerators_of(^E)):] >> [&]<auto e> {
        if (value == [:e:]) {
            result = std::meta::identifier_of(e);
        }
    };
    return result;
}

enum Color { red, green, blue };
static_assert(enum_to_string(Color::red) == "red");
static_assert(enum_to_string(Color(42)) == "<unnamed>");

int main() {
    Color red = Color::red;
    std::cout << enum_to_string(red) << std::endl;
    return 0;
}

应用场景

  • 类型描述自动生成: 通过反射轻松提取类型信息.
  • 代码生成工具: 基于反射实现自动代码生成和序列化.
  • 复杂元编程: 减少模板代码的复杂性.

2. 合约 (Contracts)

合约为函数定义前置条件, 后置条件和断言, 提升代码的可靠性.

示例: 定义函数合约

#include <contracts> // 合约支持的头文件

int divide(int numerator, int denominator)
    pre (denominator != 0)                   // 前置条件: 分母不能为 0
    post (result: result * denominator == numerator) // 后置条件: 结果 * 分母 == 分子
{
    contract_assert(numerator >= 0);         // 断言: 分子必须是非负数
    return numerator / denominator;
}

应用场景

  • 输入验证: 确保函数调用的参数满足预期.
  • 逻辑验证: 自动检测计算结果是否符合约定.
  • 调试工具: 通过断言捕捉潜在的逻辑错误.

注意: 此功能目前仍需特定编译器支持.


3. 条件中的结构化绑定 (Structured Bindings in Conditions)

C++26 引入了在 ifwhile 条件语句中使用结构化绑定的能力, 进一步简化了错误处理流程.

示例: 改进的错误处理

#include <charconv>
#include <cstring>
#include <iostream>

void parse_int(char* str) {
    if (auto [ptr, ec] = std::to_chars(str, str + std::strlen(str), 42);
        ec == std::errc{}) {
        std::cout << "Parsed successfully.\n";
    } else {
        std::cerr << "Failed to parse: " << str << "\n";
    }
}

int main() {
    const char* buffer = "42";
    parse_int(buffer);  // 输出: Parsed successfully.
    return 0;
}

在 Compiler Explorer 中查看示例

应用场景

  • 简化异常处理: 在条件语句中直接解构返回值.
  • 提高可读性: 通过解构直接获取多个结果.

4. 包索引 (Pack Indexing)

包索引让开发者能直接访问模板参数包中的特定元素, 简化模板编程.

示例: 获取参数包的第一个和最后一个元素

#include <iostream>
#include <tuple>

template <typename... Args>
constexpr auto first_and_last(Args... args) {
    return std::make_pair(Args...[0], Args...[sizeof...(Args) - 1]);
}

int main() {
    auto [first, last] = first_and_last(1, 2, 3, 4, 5);
    std::cout << "First: " << first << ", Last: " << last << "\n";
    return 0;
}

注意: 当前示例基于提案实现, 需等待特定编译器支持.

应用场景

  • 元组操作: 直接访问和操作元组中的特定元素.
  • 参数解包: 在模板编程中高效地解包和处理参数包.
  • 代码生成: 简化生成代码时对参数包的处理.
  • 编译时计算: 在编译时对参数包进行索引和计算, 提高编译期的灵活性.
  • 容器操作: 在自定义容器中高效地访问和操作元素.

5. 饱和算术 (Saturation Arithmetic)

饱和算术为加减乘除提供安全操作, 避免溢出.

示例: 安全算术操作

#include <iostream>
#include <numeric>  // 包含饱和算术的定义

int main() {
    // 饱和加法
    int add_result = std::add_sat<signed char>(100, 30);
    std::cout << "Saturated Add: " << add_result << "\n";  // 输出: 127

    // 饱和减法
    int sub_result = std::sub_sat<signed char>(-100, 30);
    std::cout << "Saturated Sub: " << sub_result << "\n";  // 输出: -128

    // 饱和乘法
    int mul_result = std::mul_sat<signed char>(100, 30);
    std::cout << "Saturated Mul: " << mul_result << "\n";  // 输出: 127

    // 类型转换的饱和
    long large_value = 150;
    int saturated_cast_result = std::saturate_cast<signed char>(large_value);
    std::cout << "Saturated Cast: " << saturated_cast_result
              << "\n";  // 输出: 127

    return 0;
}

在 Compiler Explorer 中打开

应用场景

  • 图像处理: 确保像素值在合法范围内(如 0-255).
  • 嵌入式系统: 防止溢出带来的意外行为.

6. 为函数delete标记添加说明

通过为delete标记添加说明, 开发者能更清晰地了解函数为何被删除.

#include <functional>

void NewAPI();
void OldAPI() = delete("OldAPI() is outdated and been removed - use NewAPI().");

template <class T>
auto cref(const T&) -> std::reference_wrapper<const T>;

template <class T>
auto cref(const T&&) = delete("cref(rvalue) is dangerous!");

int main() {
    int i = 0;
    auto r1 = std::cref(i);   // OK
    auto r2 = std::cref(42);  // Error, best match is deleted

    return 0;
}

在 Compiler Explorer 中打开

参考这篇博客:What =delete means

应用场景

  • API 更新: 清晰地标记过时的函数, 引导用户使用新的 API.
  • 安全性: 阻止危险的函数调用, 提高代码的安全性.

7. 匿名占位符的改进

#include <tuple>

[[nodiscard]] int foo() { return 0; }

[[nodiscard]] std::tuple<int, int, double> tuple() { return {0, 1, 1.0}; }

int multi() {
    auto _ = 1;                  // OK
    auto _ = 2.0;                // OK, no conflict
    auto _ = "string";           // OK, no conflict
    auto [ret, _, _] = tuple();  // OK, no conflict
    // return _; // Error, `_` has multi definition
    return ret;
}

int main() {
    // before C++26
    [[maybe_unused]] int a = foo();  // OK
    std::ignore = foo();             // OK
    static_cast<void>(foo());        // Not recommended

    // from C++26
    auto _ = foo();

    auto _ = multi();

    auto [ret, _, _] = tuple();
    return ret;
}

在 Compiler Explorer 中打开

8. 用户自定义 static_assert 错误信息

#include <format>

template <typename T>
void test_fun(T a) {
    static_assert(
        sizeof(T) == 1,
        std::format("Unexpected sizeof: expect 1, got {}", sizeof(T)));
}

int main() {
    test_fun('c');  // OK
    // test_fun(1);    // error
}

在 Compiler Explorer 中打开

9. 为花括号初始化的内容提供静态存储支持

std::vector<char> v = {
    #embed "2mb-image.png"
};

这段代码中的 #embed 指令可以让大型文件的数据在编译时直接嵌入为静态存储的一部分, 从而提高加载效率.

10. 新的头文件<debugging>

#include <debugging>
int main() {
    std::breakpoint_if_debugging();  // stop if in debugger
}

尚无编译器支持.

总结

C++26 的特性为现代 C++ 编程带来了更多的灵活性和高效性, 通过这些改进, C++ 程序员将能够更轻松地编写出高性能的现代化代码.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/945307.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【React】- 跨域PDF预览、下载(改文件名)、打印

我们经常会碰到跨域来方位PDF&#xff0c;同时需要下载、打印的需求&#xff0c;通常由于浏览器的安全策略&#xff0c;可以预览&#xff0c;但是下载和打印可能会受限&#xff0c;这时候怎么办呢&#xff1f; 1.创建一个隐藏的标签 要下载 iframe 中的 PDF 文件&#xff0c;…

Ps:创建数据驱动的图像

在设计实践中&#xff0c;常常需要处理大量内容变化但设计格式统一的任务&#xff0c;例如批量生成名片、工作证、学生证、胸牌、奖状或证书甚至图册。这些工作如果逐一手动制作&#xff0c;不仅耗时费力&#xff0c;还容易出错。 为解决这一问题&#xff0c;Photoshop 提供了强…

Kotlin 协程基础知识总结六 —— 协程 Flow 的综合应用

1、项目描述与搭建 &#xff08;P92~P94&#xff09;我们会将几个 Flow 的应用实例放在同一个 Demo 中&#xff0c;主页就是一个 Activity 里包含一个按钮&#xff0c;点击按钮跳转到对应的功能展示页面上。整体架构采用一个 Activity 多个 Fragment 的结构&#xff0c;结合 J…

环,域,体,整区,理想,极大理想,

环&#xff1a; 定义&#xff1a; 加法交换群 乘法半群 分配律 域的定义&#xff1a; 加法交换群 乘法群&#xff08;去掉0元是交换群&#xff09; 分配律 Eg:比如整数集合不是域&#xff0c;因为对于乘法来说&#xff0c;去掉0后没有单位元了&#xff0c;但是是环 Eg…

关于Flutter应用国际化语言的设置

目录 1. Locale配置 2. 用户切换/启动自动加载缓存里面的locale 由于最近在开发app国际化设置的时候遇到一些问题&#xff0c;所以做出一些总结。 1. Locale配置 具体的初始化配置可以参考文档&#xff1a;i18n | Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 值得…

【游戏开发】游戏生产的标准与工业化,管线Pipeline的概念与设计(项目管理,资产管理)

【游戏开发】游戏生产的标准与工业化&#xff0c;管线Pipeline的概念与设计&#xff08;项目管理&#xff0c;资产管理&#xff09; 文章目录 1、管线&#xff08;Pipeline&#xff09;是什么&#xff1f;1.1 管线解决什么问题&#xff08;例子&#xff09;1.2 一个动画电影的完…

探寻 OneCode 核心优势:MVVM 进阶与前后端协同之魅

在当今的软件开发领域&#xff0c;高效、可维护且功能强大的架构是开发者们不懈追求的目标。OneCode 凭借其独特的增强版 MVVM 架构、前后端一体化特性&#xff0c;以及创新的技术如 OneCode DSM&#xff08;Domain-Specific Modeling&#xff0c;领域特定建模&#xff09;、视…

机器人C++开源库The Robotics Library (RL)使用手册(三)

进入VS工程,我们先看看这些功能函数及其依赖库的分布关系: rl命名空间下,主要有八大模块。 搞定VS后将逐个拆解。 1、编译运行 根据报错提示,配置相应错误的库(根据每个人安装位置不同而不同,我的路径如下:) 编译所有,Release版本耗时大约10分钟。 以rlPlan运动…

ISP代理与住宅代理的区别

了解ISP代理 通常称为互联网服务提供商代理&#xff0c;通过服务提供商将用户直接连接到互联网。这些代理利用互联网服务提供商的网络&#xff0c;通常提供广泛的IP地址池。ISP代理通常快速可靠&#xff0c;非常适合一般浏览和常规互联网使用场景。 了解住宅代理 相比之下&a…

【ArcGIS Pro】完整的nc文件整理表格模型构建流程及工具练习数据分享

学术科研啥的要用到很多数据&#xff0c;nc文件融合了时间空间数据是科研重要文件。之前分享过怎样将nc文件处理成栅格后整理成表格。小编的读者还是有跑不通整个流程的&#xff0c;再来做一篇总结篇&#xff0c;也分享下练习数据跟工具&#xff0c;如果还是弄不了的&#xff0…

使用 Navicat 官方免费版来实现从 DAT 文件填充 MySQL 8 表

在异构存储库之间迁移数据&#xff08;即源数据库和目标数据库来自不同供应商的不同数据库管理系统&#xff09;会遇到一些挑战。在某些情况下&#xff0c;可以同时连接两个数据库。但有时根本无法实现。面对这样的困境&#xff0c;数据库从业者别无选择&#xff0c;只能从转储…

Three.js滚动画案例精选

今天为大家带来 3 个基于滚动动画的网站 Demo&#xff0c;它们不仅视觉效果惊艳&#xff0c;而且每个案例的源码都已开源在 GitHub&#xff0c;方便大家学习和借鉴&#xff01; 3D照片墙滚动 通过滚动操作实现 3D 网格效果以及动态过渡动画。这个案例使用了 GSAP 的 SplitTex…

今日收获(C语言)

一.文件的打开 有这样一个结构体&#xff0c;它内部是文件信息区&#xff0c;文件信息区中的变化可以影响到硬盘中的数据。这个结构体的名字是FILE。我们如果想要写代码对文件进行各种操作&#xff0c;就需要一个指向文件信息区的指针&#xff0c;这个指针的类型是FILE*&#…

【C++】九九乘法表编程题详解与多角度对比分析

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 &#x1f4af;前言&#x1f4af;题目概述题目描述 &#x1f4af;老师的实现方法代码解析优点不足 &#x1f4af;我的实现方法代码解析优点不足 &#x1f4af;实现方法对比&#x1f4af;优化与扩展代码优化…

RK3568 bsp 9 - USB调试记录

文章目录 1、环境介绍2、RK3568 USB资源介绍3、配置目标4、dts配置4.1、USB3.0 OTG4.2、USB2.0 Host 2 和 USB2.0 Host 3 5、kernel配置5.1、USB PHY CONFIG5.2、USB Host CONFIG5.3、USB OTG CONFIG5.4、USB外设CONFIG5.4.1、Mass Storage Class CONFIG5.4.2、USB HID CONFIG …

图像描述/字幕开源模型与数据集全览

图像描述/字幕&#xff08;Image Captioning&#xff09;是用文字描述图像内容的任务&#xff0c;属于计算机视觉和自然语言处理的交叉领域。大多数图像描述系统采用编码器-解码器&#xff08;encoder-decoder&#xff09;框架&#xff0c;其中输入图像被编码为中间表示形式&am…

mongodb(6.0.15)安装注意事项,重装系统后数据恢复

window10系统 上周重装了系统&#xff0c;环境变量之类的都没有了。现在要恢复。 我电脑里之前的安装包没有删除&#xff08;虽然之前也没在C盘安装&#xff0c;但是找不到了&#xff0c;所以需要重新下载安装&#xff09;&#xff0c;长下图这样。这个不是最新版本&#xff0…

Redis单线程快的原因

基于内存操作&#xff1a;Redis将数据存储在内存中&#xff0c;使得数据的读写速度极快&#xff0c;这是其性能优势的主要原因。单线程避免上下文切换&#xff1a;在多线程环境下&#xff0c;CPU核数有限&#xff0c;线程上下文切换会带来性能损耗。Redis采用单线程&#xff0c…

IOS safari 播放 mp4 遇到的坎儿

起因 事情的起因是调试 IOS 手机下播放服务器接口返回的 mp4 文件流失败。对于没调试过移动端和 Safari 的我来说着实费了些功夫&#xff0c;网上和AI也没有讲明白。好在最终大概理清楚了&#xff0c;在这里整理出来供有缘人参考。 问题 因为直接用 IOS 手机的浏览器打开页面…

import org.springframework.data.jpa.repository.JpaRepository<T, ID>;

org.springframework.data.jpa.repository.JpaRepository<T, ID> 接口中的 ID 类型参数。 理解 JpaRepository<T, ID> 中的 T 和 ID&#xff1a; T (Type): T 代表的是你想要操作的 实体类 的类型。例如&#xff0c;如果你有一个名为 User 的实体类&#xff0c;那…