开窗见月,霜天悄然,欲更小文,以为消遣。 本篇以解析 CSV 为例,再谈 C++20 的使用。网上方法,颇为陈旧,看新方式何以优雅实现。 开始之前,定义为先: Comma-separated values (CSV) is a text file format that uses commas to separate values. A CSV file stores tabular data (numbers and text) in plain text, where each line of the file typically represents one data record. Each record consists of the same… Continue Reading Parsing CSV Files in C++20

前两章主要集中于应用实践,理论概念都是蜻蜓点水,本章将重点放在这些概念原理上,深入讲解一下。 宏二段替换 源文件扫描后,宏被替换为目标内容,替换实际上分为两个阶段。 第一阶段的替换发生在参数替换之时。 当宏函数含有参数时,该参数会被替换。只有两种情况例外,一是 token 前面含有 # 或 ## 预处理标记,二是后面紧跟着 ## 预处理标记。 例如: #define Def(x) x #define Function(x, y) x ## y #define Func(x) #x #define Fun(x) ##x // Not allowed #define Fn(x) x# // Not allowed #define Defn(x, y) # x ## y // Not allowed #define A()… Continue Reading 《产生式元编程》第三章 替换蓝染概念纤悉

上篇讲解了 Compile time for,它是遍历技术中的迭代方式之一,特别常用。 它一般与 Fold expressions 组合使用,它们两个,一个相当于编译期的 Range-based for,一个相当于编译期的 for loop。由于 std::index_sequence<N> 本身只是一个静态序列,并不具备向前迭代的能力,而 Fold expressions 天生就是干这个的,两相组合,Compile time for 的功能便可完全具备。 再者,Fold expressions 只适合用来局部访问数据,不支持全局操作,当你想要整体性操作某一数据集合时,除了递归,这种迭代方式是唯一选择。相较起来,其他方式都要更加麻烦,参考上篇的例子。 考虑之前群内讨论过的一个例子,求结构体成员个数,来对比一下几种常见的编译期遍历技术。 下面是一种递归解法: struct Any { template <class T> operator T() const; }; template <class T, class… Args> requires std::is_aggregate_v<T> consteval auto CountAggregateMembers() { if constexpr (requires {… Continue Reading T231119 几种遍历技术实现结构体成员计数的比较

先说明,本篇并不是说 Expansion statements。 遍历方式分为两种,自下而上叫迭代,自上而下叫递归。 递归往往需要多个函数(if constexpr 可以避免),一般迭代是一种更加自然的方式。前面正式文章写过大量 tuple-like 类型的遍历方法,虽然也包含了非 tuple-like 类型的迭代方法,但却是作为次要部分出现的,这篇单独摘出来再讲解一下。 tuple-like 类型就是指存在 std::tuple_size<T> 和 std::get<I>(t) 定义的类型,此类类型具备通用的遍历方式。由旧文可知,目前最简单的迭代方式是借助 std::apply: void pack_iterator_with_tuple(auto&&… args) { auto tuple = std::make_tuple(std::forward<decltype(args)>(args)…); std::apply([](const auto&… tupleArgs) { ((std::cout << tupleArgs << " "), …); }, tuple); } 当然,对于参数包来说,最简单的方式是借助 Fold expressions。 void pack_iterator_with_fold_expr(auto&&… args) { ((std::cout << std::forward<decltype(args)>(args)… Continue Reading T231111 Compile time for

这篇稍微总结一下异构类型的迭代方法。 首先是静态异构类型,主要指的就是 tuple like 类型,它们可以使用 std::apply 迭代。 void print(auto tuple_like_value) { std::apply([](const auto&… args) { (fmt::print("{} ", args), …); }, tuple_like_value); fmt::print("\n"); } int main() { // Iterate std::pair { using heterogenous_t = std::pair<int, double>; heterogenous_t container { 1, 0.8 }; print(container); } // Iterate std::tuple { using heterogenous_t =… Continue Reading T231104 异构类型迭代法