C++ 动态新闻推送 第52期

2022-03-08 14:27:01 浏览数 (1)

C 动态新闻推送 第52期

从reddit/hackernews/lobsters/meetingcpp摘抄一些c 动态

文章

  • Curious lack of sprintf scaling

数字转字符串 sprintf性能,非常垃圾,使用fmt或者std::to_chars

  • Did you know wrapping an unqualified function name in parentheses suppresses argument-dependent lookup?
代码语言:javascript复制
namespace adl {
    struct foo {};
    void bar(foo) {}
}

int main() {
    adl::foo foo;
    bar(foo);   // OK,    ADL
    (bar)(foo); // error: no ADL
}

就是名字空间内的查找

  • Did you know that C 23 added std::unreachable?
代码语言:javascript复制
#include <utility>

int main() {
    std::unreachable();
    return 42; // invokes undefined behavior
}

没啥说的,类似assert(false)

  • Did you know that C 20 added std::erase_if for std::map and std::vector?
代码语言:javascript复制
int main() {
  std::vector v{1, 2, 3, 4};
  assert(4 == std::size(v));
  std::erase_if(v, [](const auto& e) { return e % 2;} );
  assert(2 == std::size(v));
  assert(v[0] == 2 and v[1] == 4);
}

没啥说的

  • Image Sharpening Convolution Kernels

手把手教你图像过滤,看不懂

  • Picking Fairly From a List of Unknown Size With Reservoir Sampling

图像sample 看不懂

  • Mocking virtual functions with gMock

手把手教你gmock

  • wordlexpr: compile-time wordle in c 20

几个需求,编译期打印字符串,编译期生成随机数 第一个简单,就是fixed_string static assert

代码语言:javascript复制
struct ct_str
{
    char        _data[512]{};
    std::size_t _size{0};

    template <std::size_t N>
    constexpr ct_str(const char (&str)[N]) : _data{}, _size{N - 1}
    {
        for(std::size_t i = 0; i < _size;   i)
            _data[i] = str[i];
    }
};

template <ct_str> struct print;

constexpr ct_str test()
{
    ct_str s{"Welcome to Wordlexpr!"};
    s._data[0] = 'w';
    s._data[11] = 'w';
    s._data[20] = '.';
    return s;
}

print<test()> _{};

第二个就是用fixed_string来做生成随机数的生成器,让外部指定seed和字符串,然后编译的时候改一改就行了

  • [What if vector::iterator were just T*?](https://quuxplusone.github.io/blog/2022/03/03/why-isnt-vector-iterator-just-t-star/)

语言律师新活,如果itor是T*,会有一大堆冲突问题,后面是一大堆列举。这里不提了

  • Zero-cost exceptions aren’t actually zero cost

异常,我劝你别用

  • 3 interesting behaviors of C casts 介绍cast
  • C header files and inter-class connections

c 编译依赖和头文件的问题。属于老生常谈的讨论

  • C Benchmarking Tips for Beginners

google benchmark教程,几个案例

基本的阻止优化

代码语言:javascript复制
static void i32_addition_semirandom(bm::State &state) {
    int32_t a = std::rand(), b = std::rand(), c = 0;
    for (auto _ : state)
        bm::DoNotOptimize(c = (  a)   (  b));
}

一个简单的数学算法对比

代码语言:javascript复制
static void f64_sin(bm::State &state) {
    double argument = std::rand(), result = 0;
    for (auto _ : state)
        bm::DoNotOptimize(result = std::sin(argument  = 1.0));
}

static void f64_sin_maclaurin(bm::State &state) {
    double argument = std::rand(), result = 0;
    for (auto _ : state) {
        argument  = 1.0;
        result = argument - std::pow(argument, 3) / 6   std::pow(argument, 5) / 120;
        bm::DoNotOptimize(result);
    }
}
static void f64_sin_maclaurin_powless(bm::State &state) {
    double argument = std::rand(), result = 0;
    for (auto _ : state) {
        argument  = 1.0;
        result = argument - (argument * argument * argument) / 6.0  
                 (argument * argument * argument * argument * argument) / 120.0;
        bm::DoNotOptimize(result);
    }
}

[[gnu::optimize("-ffast-math")]]
static void f64_sin_maclaurin_with_fast_math(bm::State &state) {
    double argument = std::rand(), result = 0;
    for (auto _ : state) {
        argument  = 1.0;
        result = argument - (argument * argument * argument) / 6.0  
                 (argument * argument * argument * argument * argument) / 120.0;
        bm::DoNotOptimize(result);
    }
}

注意这个attrbute用法。最后一种非常快

整数除法

代码语言:javascript复制
static void i64_division(bm::State &state) {
    int64_t a = std::rand(), b = std::rand(), c = 0;
    for (auto _ : state)
        bm::DoNotOptimize(c = (  a) / (  b));
}

static void i64_division_by_const(bm::State &state) {
    int64_t money = 2147483647;
    int64_t a = std::rand(), c;
    for (auto _ : state)
        bm::DoNotOptimize(c = (  a) / *std::launder(&money));
}
static void i64_division_by_constexpr(bm::State &state) {
    constexpr int64_t b = 2147483647;
    int64_t a = std::rand(), b;
    for (auto _ : state)
        bm::DoNotOptimize(c = (  a) / b);
}

constexpr非常快

硬件加速

代码语言:javascript复制
[[gnu::target("default")]] static void u64_population_count(bm::State &state) {
    auto a = static_cast<uint64_t>(std::rand());
    for (auto _ : state)
        bm::DoNotOptimize(__builtin_popcount(  a));
}
[[gnu::target("popcnt")]] static void u64_population_count_x86(bm::State &state) {
    auto a = static_cast<uint64_t>(std::rand());
    for (auto _ : state)
        bm::DoNotOptimize(__builtin_popcount(  a));
}

如果硬件支持popcnt指令,有优化提升

  • History of non-standard-layout class layouts

里面有个表格概括,就不截图了

视频

  • C Weekly - Ep 313 - The constexpr Problem That Took Me 5 Years To Fix!

还是模板 fixed_string/array 这种场景,如果fixed_string/array是相同的,由于模板实例化相同的实例会合并,所以说这就是一种压缩效果,复用数据段。

  • SwedenCpp YT - Arno Lepisk: Testing non-compiling code

就是static assert type traits没啥说的

  • Petter Holmberg: Functional parsing in C 20

0 人点赞