统一的侵入式链表

「完全拒绝UB是缺乏工程实践的表现」 ——TypeCombinator

前言

去年,我在写下了在purecpp上的第一篇文章——《统一的侵入式链表》,文章里最初的原型是几年前是使用C语言实现的,一直躺在我的私人仓库里吃灰。直到去年我在做调度器优化的相关工作的时候我才回想起来,于是将其拿出来用C++改写,并做了一些尝试和探索(见GitHub仓库uit),通过这次分享和提问,我得到了ykiko迅速且精准的回答,也意识到了这个idea和C++标准之间的矛盾,遂弃坑了一段时间,但是,终极问题的种子一直深埋脑海——如何让这个idea能够work呢

在后续的日常开发中,我又有了新的思路,实践之后,先前无法通过的测试均能在三大编译器上通过,当然其中过程也并非一帆风顺,哄了ClangGCC好几小时,这两位才让我构造的测试通过,至于MSVC嘛,向来情绪稳定,毫无意外地通过了测试。需要说明的是新方案不仅在用法上更灵活,也没有引入任何额外分支或其他消耗,且不需要加任何额外的编译选项或是在源码中加一些属性,在最高优化等级下,三大编译器均可通过所有测试!

forward_like_tuple

「把一个人的温暖转移到另一个的胸膛」
——陈奕迅《爱情转移》

前言

C++23语核更新太少,一直没有动力去升级,不过考虑到明年是2026年了,26年用C++23还算合理吧?C++23中,能大幅简化代码的特性,首当其冲的恐怕就是deducing this了,于是先使用该特性对代码进行了一番改造,终于不用再反复写&const &&&const &&这几种成员函数了,搭配上forward_like,一个成员函数即覆盖所有情形,起初还算顺利,但是改造在tuple时却碰到了单元测试编译报错的问题,一探之下,发现forward_like并不适用于tupleget方法。

简单点,元编程的方式简单点

一直以来,C++模板元编程的代码都极不直观,直到我看到了这样一段代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
template<class... Ts>
struct example {
  mp::apply_t<std::variant,
      std::array{mp::meta<Ts>...}
    | std::views::drop(1)
    | std::views::reverse
    | std::views::filter([](auto m) { return mp::invoke<std::is_integral>(m); })
    | std::views::transform([](auto m) { return mp::invoke<std::add_const>(m); })
    | std::views::take(2)
    | std::ranges::to<mp::vector<mp::info>>()
  > v;
};

static_assert(
  typeid(std::variant<const int, const short>)
  ==
  typeid(example<double, void, const short, int>::v)
);
0%