C++23
C++23新特性
静静地躺着
风起则飞扬,风平则静安!
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
C++(23):invoke_r
他的主要作用是统一返回类型,特别是当你想在模板代码里明确约束“这个调用最终必须能当作某种类型返回”。C++23提供了invoke_r<R>,把返回值直接转换为类型R。需要说明的是:如果 R 是 void,它会调用函数但丢弃返回值。C++17引入了invoke。原创 2026-04-28 22:24:55 · 217 阅读 · 0 评论 -
C++(23):to_underlying
C++11可以通过underlying_type_t获取底层数据值,但是略显麻烦。为此C++23提供了to_underlying用于获取枚举类的底层数据值。枚举类不会像旧式枚举那样自动转成整数,这能避免很多隐式转换错误。C++11引入了枚举类。原创 2026-04-28 21:31:19 · 52 阅读 · 0 评论 -
C++(23):move_only_function
move_only_function像std::function 一样“装一个可调用对象”,但这个包装器只能移动,不能拷贝。它主要用来保存那些“不可拷贝、只能移动”的可调用对象,比如捕获了 unique_ptr 的 lambda。这个例子里,lambda 捕获了一个 unique_ptr,所以它不能被复制,只能移动。原创 2026-04-21 16:13:09 · 48 阅读 · 0 评论 -
C++(23):ranges::find_last
简单的说,find_last就是从反向查找符合条件的值,然后返回一个从这个值开始的subranges。#5,find_last_if_not,找的是不符合条件的值,既不是1也不是2,所以输出。#4,由于pred(abs(x)),所以不存在-3,所以没有找到。#6,寻找既不是1也不是2和3的值,所以没找到。#2,由于是寻找最后一个-3,没有找到。原创 2026-04-13 16:45:54 · 145 阅读 · 0 评论 -
C++(23):iota
的意思是初始化一个迭代器的vector,里面有list.size()个,也就是8个迭代器,但是初值都是空。他的主要作用是:把区间 [first, last) 的每个元素依次赋为从。开始的递增值(++)原创 2026-04-13 16:01:07 · 67 阅读 · 0 评论 -
C++(23):反射的实现9 增加支持函数重载以及多线程
修改为std::unordered_map<std::string, std::vector<AnyCallable>>,同一个名字可以保存多个函数封装。根据是否启用mutex,选择是使用shared_mutex还是NullSharedMutex(无锁)将AnyCallable压入vector,因此可以保存多个AnyCallable对象。可以看到现在可以处理函数重载以及线程安全了。可以选择是否支持mutex的类实例。匹配输入参数,来寻找目标函数。2.2mutex的选择。原创 2026-02-13 15:00:20 · 82 阅读 · 0 评论 -
C++(23):反射的实现8 处理返回值 func_call_wrap.hpp解析
这里实现了将函数保存到map,然后在根据名字调用函数,但是有一点有点麻烦,就是需要手动处理返回值类型,func_call_wrap.hpp进一步的优化了返回值的自动转换。该函数用于判断返回值类型,如果是原生基本类型,则调用any_to_arithmetic进行转换,否则调用any_cast完成类型的转换。这个类利用了隐式转换的方式来完成类型的自动转换,也就是他首先重载了()运算符,该运输符可以用于类型的隐式转换。然后()运算符调用了as -> convert。原创 2026-02-12 14:35:12 · 65 阅读 · 0 评论 -
C++(23):反射的实现7 函数map func_map.hpp解析
这个函数通过名字,从func_map_找到函数封装的为AnyCallable对象,然后传递参数进行调佣,返回值是any类型,所以需要用户手动的再将any通过any_cast<T>转变为真正的返回类型。但这几个函数用起来并不是特别的方便,因为不能直接转变为返回值,所以又提供了callByNameWrap函数,后面会对这个设计进行解释。4.callByNameAs与callByName类似,只不过调用时指定了返回值类型,所以该函数直接完成了将any转变为返回值类型。把函数先通过makeCallable。原创 2026-02-12 13:44:17 · 610 阅读 · 0 评论 -
C++(23):反射的实现6 函数封装 any_callable.hpp解析
makeCallable_impl的返回值类型是AnyCallable,这个类型将任意函数类型进行了抽象,并将函数的签名及调用封装在了对象内部。是主要的对外接口,他会区分是否为类的成员函数,然后设定Traits,之后调用makeCallable_impl完成类型绑定。这个文件的主要作用就是把各种类型的函数转变为一个通用的类型,以备后面将其保存在一个数据结构中。用于把传入的any参数转换为stored(也就是fn)实际需要的参数类型。封装了一个lambda,用于后续完成对stored的调用。原创 2026-02-11 16:55:58 · 188 阅读 · 0 评论 -
C++(23):反射的实现5 类型提取 func_type.hpp解析
首先由于lambda类型没有上述的成员函数类型,所以来到了最后的operator()处,然后获取了&T::operator()类型后,进而在通过上面的类成员函数特化完成了递归的推导。args_tuple:函数的参数的tuple表示。return_type:函数的返回值类型。arg:用于获取第几个参数的类型。用于完成类的成员函数的类型获取。用于特化了函数指针类型的提取。用于特化function类型。arity:函数的参数个数。3.function类型。原创 2026-02-11 10:56:43 · 89 阅读 · 0 评论 -
C++(23):反射的实现4 直接通过名字调用函数
增加了callByNameWrap函数,用于处理自动类型转换,这里的关键点是函数的返回值是FuncCallResult。这个类中最为关键的就是operator T(),该运算符完成FuncCallResult到目标类型的隐式转换。已经很接近实现反射了,但是这里有一点需要改进,就是调用时还需要传递返回值类型,以下是改进后的实现。这个反射的实现基本完成了,也许还有不能覆盖的场景,但是基本上把反射实现的方式说了一下。可以看到可以直接通过名字来找到函数并完成调用,而且可以直接转换为返回值类型。原创 2026-01-27 16:00:52 · 865 阅读 · 0 评论 -
C++(23):反射的实现3 通过map调用函数
callByNameWithRetType:通过函数名字调用函数,获取返回值的同时获取返回值类型。由于引入了member_function_traits,所以makeCallable略作了修改。可以看到可以通过名字来调用普通函数,lambda,函数对象,成员函数,成员函数指针。callByNameAs:通过函数名字调用函数,然后把返回值转换为想要的类型。这里又对之前的定义进行了扩展,加入对类的成员函数的处理。callByName:通过函数名字调用函数。原创 2026-01-27 11:49:42 · 287 阅读 · 0 评论 -
C++(23):反射的实现2 将函数抽象成统一的对象
makeCallable:借助makeCallable_impl将一个函数生成一个AnyCallable对象。cast_result:用于获取通过AnyCallable完成函数调用时的返回值。可以看到通过AnyCallable 可以把各种函数进行封装,然后完成调用。validate_args:用于检查函数参数的匹配。1.首先还是function_traits。AnyCallable:用于抽象所有的函数。原创 2026-01-26 21:26:22 · 171 阅读 · 0 评论 -
C++(23):反射的实现1 提取函数签名
编译程序,没有报错,所以没有触发static_assert,说明上面的function_traits可以正常的提取函数签名了。1.将各种形式的函数,包括成员函数,function函数对象,lambda函数全都推导为function_traits类型。3.function_traits的args_tuple推导为通过函数参数构建的tuple<Args...>类型。2.function_traits的return_type推导为函数的返回值类型。4.function_traits的arity表示参数的个数。原创 2026-01-26 18:12:16 · 71 阅读 · 0 评论 -
C++(23):一种通用log模块的实现
2.common_api.h定义了一些辅助函数,其中最为重要的就是toStr,用于将各种数据结构转为string。1.log_out.h定义了log模块的主要功能,包括设置输出等级以及输出方法还有输出内容。可以看到,基本数据类型,容器,自定义数据类型,都可以直接通过logXXX函数进行直接输出。3.key_value,h用于定义自己的数据结构,演示如果把自定义类型输出为字符串。介绍了一种比较通用的log实现,但是需要使用nlohmann/json.hpp。4.main.cpp用于完成log模块的测试。原创 2026-01-12 10:35:19 · 52 阅读 · 0 评论 -
C++(23):ranges::to
C++23为容器之间的转换提供了一个比较方便的方案,那就是ranges::to。可以看到通过ranges::to可以非常方便的完成容器间的转换。原创 2026-01-13 21:01:42 · 71 阅读 · 0 评论 -
C++(23):获取异常的调用栈信息
1.traced_level1在调用链上抛出了traced_error,这个对象里面有一个trace成员,用于记录当时的调用栈信息,所以[A]输出可以看到完整的调用栈。3.如果是普通异常,也就是没有在抛出异常时记录trace,那么在catch时也是无法查看到抛出异常时的调用栈情况的。2.如果在catch处打印调用栈,只能看到被调用时的栈情况,无法看到抛出异常时的栈情况,参考[B]输出。4.使用stacktrace,编译的时候需要链接库-lstdc++exp。原创 2026-01-22 15:38:04 · 205 阅读 · 0 评论 -
C++(23):flat_map
C++23引入了几个新的容器flat_{set | multiset | map | multimap},这些容器其实是通过连续内存保存的经过排序后的数据。咋一听起来感觉这个设计有点无用,因为使用map这类关联容器的优点就是可以快速的插入,删除,然后查找的效率也蛮好的。如果使用连续内存(像vector),那么插入和删除的效率必然很低,因为需要移动数据。1.flat_map占用的内存更少,因为map需要有额外的指针。1.频繁插入/删除/动态更新,因为flat_map是连续内存。2.遍历很快,因为是连续内存。原创 2026-01-22 17:44:09 · 88 阅读 · 0 评论 -
C++(23):views::enumerate
C++20增加了Ranges和Views,C++23又将此发扬光大,Ranges和Views已经到了相当可用的程度。原创 2026-01-23 10:37:09 · 66 阅读 · 0 评论 -
C++(23):views::zip
这也就是names.size()=4, zipped size follows the shorter ages.size()=3。2.views::zip 迭代得到的元素类型是“tuple-like”,基本上可以认为是tuple<T1&, T2&, ...>所以可以通过解构直接修改源数据,也就是上例age += 1最后确实修改了ages中的值。1.zip是是基于多个ranges中最短的那个作为输出的范围。当然如果源数据是const类型的,那是不能修改值的。原创 2026-01-23 11:19:58 · 276 阅读 · 0 评论 -
C++(23):返回右值引用时省略move
需要说明的是,虽然编译器允许省略move的操作,但也就仅此而已,不会为生命周期或引用悬挂多做任何事情,所以如果使用不当,还是会造成引用悬挂。C++20中,returnTest必须通过move(t)的方式返回,因为t本身是一个左值。比如下面的程序使用Test&& t1 = returnTest(Test(30));C++23,简化了return的语句,对于这种情况可以直接返回t。可以看到先完成了移动,然后调用的析构。原创 2026-01-04 22:15:12 · 62 阅读 · 0 评论 -
C++(23):print直接输出容器内容
【代码】C++(23):print直接输出容器内容。原创 2026-01-10 18:03:50 · 275 阅读 · 0 评论 -
C++(23):print自定义数据结构内容
【代码】C++(23):print自定义数据结构内容。原创 2026-01-11 12:56:01 · 55 阅读 · 0 评论 -
C++(23):将容器和自定义数据结构转换为string
可以看到通过to_string_fmt我们可以把容器和自定义类型都转换为string,甚至也包含容器和自定义类型的组合。可以通过print打印容器和自定义数据结构,那么那么有没有方法可以直接将其内容转换为string呢?原创 2026-01-11 13:05:26 · 234 阅读 · 0 评论 -
C++(23):利用this参数实现lambda的递归调用
相当于重载了其operator运算符,加入了this参数,因此我们可以利用其完成递归调用。可以大致认为lambdaAdd与DoAdd的实现类似,只不过lambda是一个匿名类。所以实际上lambda也是一个类型,并且有其成员函数operator。因此可以利用this实现lambda的递归调用。原创 2026-01-02 14:27:24 · 230 阅读 · 0 评论 -
C++(23):实现一个通用的线程池
6.任务保存在tasks.emplace([task]() { (*task)();}这个lambda。3.submit的精髓是将函数和参数绑定后,完成其调用,就不再需要参数,因此就可以将其封入一个void()类型的lambda,这样就可以将这个统一形式的lambda保存到std::queue<std::function<void()>> tasks;2.submit函数用于向线程池派发任务,可以看到R是函数的返回类型,而task是将函数与参数绑定后的packaged_task对象。原创 2025-11-28 21:27:55 · 200 阅读 · 0 评论 -
C++(23):实现一个通用的类,封装各种函数,保存到vector中
注:这种方式只能保存函数参数快照,也就是在生成AnyCallable对象时,函数的参数也随之绑定了,不能动态的修改,如果是动态参数需要后续再生成AnyCallable对象。1.我们创建了一个funTrans函数,用于把函数的静态信息,比如调用参数和返回值类型保存到一个AnyCallable对象中。4.在需要的时候从vector中取出AnyCallable对象,调用其接口完成函数的调用,获取返回值。5.AnyCallable类提供了两种获取返回值的方式,一种是通过函数的返回值,另一种是通过传递参数。原创 2025-11-28 15:18:53 · 266 阅读 · 0 评论 -
C++(23):延长for循环临时变量生命期
编译程序:g++ -O0 -g -fsanitize=address,undefined -fno-omit-frame-pointer -o m m.cpp --std=c++20。编译程序:g++ -O0 -g -fsanitize=address,undefined -fno-omit-frame-pointer -o m m.cpp --std=c++23。循环冒号以后的初始化器部分中,除了函数传参以外的所有生成的临时对象生命期都被自动延长到循环结束之后。可以看到产生了悬挂引用。原创 2025-10-31 23:19:53 · 121 阅读 · 0 评论 -
C++(23):通过print和printIn进行输出
说实话也许是习惯了C语言的printf输出,所以使用cout进行输出其实体验并不觉得怎么好,也许是每次都要<<输出时,需要多写一个字符吧。也许是听到了一些程序员的心声,C++23增加通过print和printIn进行输出。std::println:行为与 std::print 相同,但在输出后。适合需要在同一行多次输出或精确控制换行位置的场景。std::print:按给定的格式把内容写出,但。方便用于“输出一整行”的场景。原创 2025-10-27 22:23:20 · 256 阅读 · 0 评论 -
C++(23):lambda可以模版参数
可以看到f1和f2的输出是一样的,那么在lambda中使用模版有什么意义呢,我觉得最为主要的是可以约束参数a和b是同一类型的。可以看到如果传递不同类型的参数,使用模版的lambda会编译报错的,但是使用auto的lambda不会。可以看到f1使用了模版参数。原创 2025-10-23 21:45:20 · 70 阅读 · 0 评论 -
C++(23):contains检查字符串是否包含子字符串
运行输出:Hello, World!编译:g++ -o m m.cpp -std=c++23。原创 2025-10-22 23:11:11 · 106 阅读 · 0 评论 -
C++(23):定义类的静态()运算符函数
C++23,可以定义类的静态运算符函数,从而直接使用直接进行调用。编译:g++ -o m m.cpp -std=c++23。原创 2025-10-21 22:18:21 · 66 阅读 · 0 评论 -
C++(23):利用this参数更方便的实现CRTP
介绍了C++23为类成员引入了this参数。可以看到,实现了CRTP。原创 2025-02-19 21:48:29 · 270 阅读 · 0 评论 -
C++(23):为类成员函数增加this参数
可以看到通过这种方式可以更方便的基于this对象的类型对函数进行重载。原创 2025-02-19 21:33:37 · 194 阅读 · 0 评论 -
C++(23):lambda可以省略()
【代码】C++(23):lambda可以省略()原创 2025-02-19 21:26:11 · 147 阅读 · 0 评论 -
C++(23):unreachable
2.调用func(1)并没有引起程序段错误,程序还顺利的执行完了,只是忽略掉了std::unreachable()后面的代码。这两个意外,让我暂时还没有搞清楚unreachable的具体作用是什么,日后了解了,再进行补充。1.func(1);明显的进入了unreachable,但编译的时候并没有报错。原创 2025-02-18 21:42:57 · 169 阅读 · 0 评论 -
C++(23):支持多维数组运算符
当然如果不想处理访问越界的情况,可以不必处理数组索引的检查。可以看到通过这种方式可以更为便捷的访问多维数组。原创 2025-02-18 21:17:40 · 801 阅读 · 0 评论 -
C++(23):多维数组下标
可以看到C++23中的operator[]可以支持多个参数表示的多个维度了。原创 2024-07-02 21:42:32 · 319 阅读 · 0 评论 -
C++(23):新的错误返回机制expected
4.调用函数时返回的expected值,如果转bool后为true,代表函数正确的执行了,可以通过类似*result或result.value()获取到返回值。5.如果函数执行错误了,那么可以通过result.error()返回错误对象,比如DivE,继而通过错误对象得到错误值result.error().err。2.expected的第二个模版参数DivE代表的是函数执行错误时的类型,可以是原生类型也可以是自定义类型。传统的C++程序,有的时候既想要知道函数是否正确的执行了,又想要知道返回的结果。原创 2024-07-28 21:54:32 · 501 阅读 · 0 评论 -
C++(23):lambda如果没有参数可以省略()
可以看到C++23中进一步的优化了lambda,使其更加便于使用。在定义lambda时,如果没有参数,那么C++23可以省略()原创 2024-03-02 11:42:55 · 181 阅读 · 0 评论
分享