Skip to content

败犬日报 2024-11-20

1. 关于 safe c++ 的小作文

https://izzys.casa/2024/11/on-safe-cxx/

2. 别名不会产生新的符号

看一下这个代码,报错是 error: pack expansion argument for non-pack parameter 'T0' of alias template 'template<class T0, class ... Ts> using Tint = int'

cpp
template <typename T0, typename... Ts>
using Tint = int;

template <typename... Ts>
using A = Tint<Ts...>;

https://wg21.link/cwg1430

由于 C++ 规定,别名(using)不能产生任何新的符号,所以在实例化之前就得全替换掉。但是包参数(typename... Ts)展开到非包参数(int)上就没法做这样的替换。

解决办法是套个 struct:

cpp
template <typename T0, typename... Ts>
struct Tint {
    using type = int;
};

template <typename... Ts>
using A = Tint<Ts...>;

模板的 name mangling 一个误解是 mangling 的类型是在整个模板替换完之后,把最终的类型给 mangling 了。但是实际上不是的。

https://godbolt.org/z/f46zKo31b 这里是直接 mangling 这个完全限定的特化类型。

3. 一个类有全局变量实例,且这个类的构造函数里通过这个全局变量读数据

那么这个全局变量的值是未指定的,后续需要重新赋值。

https://eel.is/c++draft/class.cdtor#example-2

4. 编译期笛卡尔积

比如 std::tuple A {m, n}, std::tuple A {o, p, q}, std::tuple A {x, y, z} 然后生成 std::tuple<std::tuple<m, o, x>, ...> 这个类型。

这个还是比较麻烦的,群友提供了实现 https://godbolt.org/z/en34P95cq

5. c++98 古法炼钢实现 lambda

就是用 struct 模拟 lambda 行为:

cpp
#include <iostream>
int main() {
    struct lambda {
        int& y;
        lambda(int& y) : y(y) {}
        int operator()(int x) { return x + y; }
    };
    int y = 10;
    lambda f(y); // 模拟 [&](int x) { return x + y; }
    auto g = f(5);
    std::cout << g << std::endl;
    return 0;
}

群友公司根据这个原理写了一个宏实现的闭包。