前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >C++ 中文周刊 2024-03-03 第150期

C++ 中文周刊 2024-03-03 第150期

作者头像
王很水
发布2024-07-30 15:01:20
870
发布2024-07-30 15:01:20
举报
文章被收录于专栏:C++ 动态新闻推送

RSS https://github.com/wanghenshui/cppweeklynews/releases.atom

欢迎投稿,推荐或自荐文章/软件/资源等 评论区留言

本期文章由 黄亮Anthony Amnesia 赞助

最近沸沸扬扬的白宫发文,转向更安全的语言,明示c++不行

除了把NSA之前的观点重新提出来之外,没有任何新东西

就像个想离婚的在这里埋怨不想过了,死鬼你也不改你看人家xx语言

要我说这就是美帝不行的原因,从上到下都没有耐性我靠

最近很忙视频都没来得及看。后面慢慢补吧,视频可能单独发总结

资讯

标准委员会动态/ide/编译器信息放在这里

编译器信息最新动态推荐关注hellogcc公众号 本周更新 2024-02-21 第242期

本台记者 kenshin报道,visual studio最近更新了非常有用的功能,分析编译时间之类,分析字段内存布局,分析include等等

感兴趣 可以更新一下 What’s New for C++ Developers in Visual Studio 2022 17.9 https://devblogs.microsoft.com/cppblog/whats-new-for-cpp-developers-in-visual-studio-2022-17-9/?WT.mc_id=academic-0000-abartolo

另外clang gcc有单独的工具,比如ftime-trace,比如 这个 https://github.com/aras-p/ClangBuildAnalyzer

xmake 2.8.7发布

https://github.com/xmake-io/xmake/wiki/Xmake-v2.8.7-released,-Add-cosmocc-toolchain-support,-build%E2%80%90once-run%E2%80%90anywhere

boost新parser正在review中 https://lists.boost.org/Archives/boost/2024/02/255957.php

类似boost spirit,代码在这里 https://github.com/tzlaine/parser

think-cell出了个意见,他们在自己的库里维护了boost spirit,觉得重新造轮子不太合理,详情见 https://www.think-cell.com/en/career/devblog/parsers-vs-unicode

文章

Rage Against The Glue: Beyond Run-Time Media Frameworks with Modern C++ https://cnrs.hal.science/hal-04090584/document

音视频领域有个 M x N问题

不同的media processors 在N种平台上导致api复杂度上升不可维护

考虑一种接口设计方法,让代码更简练

琢磨半天结果是concept + boost pfr之类的检测接口/策略模版

代码在这里 https://github.com/celtera/avendish

还有一些其他的想法 在这里 https://ossia.io/posts/reflection/

constexpr and consteval functions https://biowpn.github.io/bioweapon/2024/02/17/constexpr-consteval-function.html

记住这段代码就行了

代码语言:javascript
复制
// This is a pure compile-time function.
// Any evaluation is fully done at compile-time;
// no runtime code will be generated by the compiler, just like `static_assert`.
consteval size_t strlen_ct(const char* s) {
    size_t n = 0;
    for (; s[n] != '\0'; ++n);
    return n;
}

// This is a pure runtime function, which can only be invoked at runtime.
size_t strlen(const char* s);

// This function can be invoked both at both compile-time and at runtime,
// depending on the context.
constexpr size_t strlen_dual(const char* s) {
    if consteval {
        return strlen_ct(s); // compile-time path
    } else {
        return strlen(s);    // runtime path
    }
}

constexpr最好两种分支都实现,避免意外的问题

How to debug C and C++ programs with rr https://developers.redhat.com/blog/2021/05/03/instant-replay-debugging-c-and-c-programs-with-rr#

其实rr和gdb record差不多,感觉可以用这个文档例子做个视频,这里标记一个TODO

https://github.com/rr-debugger/rr?tab=readme-ov-file

Undefined behavior in C and C++ https://lumagraph.ie/undefined-behavior

讲UB产生的场景,以及如何避免,给的方案编译flag ubsan以及换个语言,我谢谢你

Measuring energy usage: regular code vs. SIMD code https://lemire.me/blog/2024/02/19/measuring-energy-usage-regular-code-vs-simd-code/

lemire新活,只要你的代码足够快,即使是simd这种费电的指令相比而言整体费电也不多

代码在这里 https://github.com/lemire/Code-used-on-Daniel-Lemire-s-blog/tree/master/2024/02/19

值得复现一下

My late discovery of std::filesystem - Part I https://www.sandordargo.com/blog/2024/02/28/std-filesystem-part1-paths-and-operations

介绍fs相关api,比如遍历之类的,我就不列出来了

How to write unit tests in C++ relying on non-code files? https://www.sandordargo.com/blog/2024/02/21/cpp-tests-with-resources

介绍非代码文件怎么和代码编译到一起的,bazel/cmake都有类似configfile的方法。embed赶紧来吧

Navigating Memory in C++: A Guide to Using std::uintptr_t for Address Handling https://blog.feabhas.com/2024/02/navigating-memory-in-c-a-guide-to-using-stduintptr_t-for-address-handling/

为什么用它,用int32 int64之类的类型,reinterpret cast可能会有fpermissive报错,比如

代码语言:javascript
复制

#include <cstdint>

namespace HAL {
class UART {
public:
 explicit UART(std::uint32_t base_address); 
 void write(std::byte byte);
 std::byte read() const;
 // ...
private:
 struct Registers* const registers;
};
}

constexpr std::uint32_t com1_based_address = 0x4002'0000U;

int main() {
 HAL::UART com1{com1_based_address}; 
 com1.write(std::byte{0x5A});
 auto val = com1.read();
 ...
}
namespace {
 struct Registers // layout of hardware UART
{ 
  std::uint32_t status;     // status register
  std::uint32_t data;      // data register
  std::uint32_t baud_rate;    // baud rate register
  ...
  std::uint32_t guard_prescaler; // Guard time and prescaler register
 };
 static_assert(sizeof(Registers) == 40, "Registers struct has padding");
 Registers Mock_registers{};
} 

// doctest
TEST_CASE("UART Construction") {
  constexpr std::uint32_t baud_115k = 0x8b;
  constexpr std::uint32_t b8_np_1stopbit = 0x200c;

  HAL::UART com3 {reinterpret_cast<std::uint32_t>(&Mock_registers)}; // 不行

  CHECK(Mock_registers.baud_rate == baud_115k);
  CHECK(Mock_registers.ctrl_1 == b8_np_1stopbit);
}

但如果把UART构造函数改成intptr就没问题

代码语言:javascript
复制
#include <cstdint>

namespace HAL {
class UART {
public:
 explicit UART(std::uintptr_t base_addr); 
 ...
};
}

// doctest
TEST_CASE("UART Construction") {
  constexpr std::uint32_t baud_115k = 0x8b;
  constexpr std::uint32_t b8_np_1stopbit = 0x200c;

  HAL::UART com3 {reinterpret_cast<std::uintptr_t>(&Mock_registers)};

  CHECK(Mock_registers.baud_rate == baud_115k);
  CHECK(Mock_registers.ctrl_1 == b8_np_1stopbit);
}

为什么不用intptr? 如果涉及到负数移动,或者做差有负数之类的,可以用intptr,其他场景还是uintptr更合适

Introduction To Low Latency Programming: Minimize Branching And Jumping https://tech.davidgorski.ca/introduction-to-low-latency-programming-minimize-branching-and-jumping/

哥们出书了,120页卖10刀有点贵我靠,书在这里 https://a.co/d/0U6KOfb

这个文章是节选,大概思路就是降低跳转和分支

  • • 勤用 && || 利用短路特性
  • • 关注能生成cmov的写法,condition mov几乎和mov差不多,利用cmov替代jump test更好,什么能生成cmov? 冒号表达式
  • • 减少虚函数使用,你用variant模拟那也是虚函数,不要自欺欺人哈
  • • inline,可以用[[gnu::always_inline]]
  • • 善用 __builtin_expect
  • • 分支改switch

一个样例

代码语言:javascript
复制
void processThisString(std::string_view input)
{
  if (input == "production") {
    processProd(input);
  } else if (input == "RC") {
    processRC(input);
  } else if (input == "beta")
    processBeta(input);
  }
}
void processThisString(std::string_view input)
{
  constexpr auto i = 0;
  switch (input[i]) {
    case "production"[i]: processProd(input); break;
    case "RC"[i]: processRC(input); break;
    case "beta"[i]: processBeta(input); break;
  }
}
1 << n vs. 1U << n and a cell phone autofocus problem https://rachelbythebay.com/w/2024/02/24/signext/
代码语言:javascript
复制

#include <stdio.h>

static unsigned long set_bit_a(int bit) {
  return 1 << bit;
}

static unsigned long set_bit_b(int bit) {
  return 1U << bit;
}

int main() {
  printf("sizeof(unsigned long) here: %zd\n", sizeof(unsigned long));

  for (int i = 0; i < 32; ++i) {
    printf("1 << %d : 0x%lx | 0x%lx\n", i, set_bit_a(i), set_bit_b(i));
  }

  return 0;
}

64位机器 31会打印什么?https://gcc.godbolt.org/z/qa3o34hrW

非常幽默

代码语言:javascript
复制
1 << 0 : 0x1 | 0x1
1 << 1 : 0x2 | 0x2
1 << 2 : 0x4 | 0x4
1 << 3 : 0x8 | 0x8
1 << 4 : 0x10 | 0x10
1 << 5 : 0x20 | 0x20
...
1 << 29 : 0x20000000 | 0x20000000
1 << 30 : 0x40000000 | 0x40000000
1 << 31 : 0xffffffff80000000 | 0x80000000

m32并没有这个问题

自底向上理解memory_order https://zhuanlan.zhihu.com/p/682286231

理解理解

Using std::expected from C++23 https://www.cppstories.com/2024/expected-cpp23/

不会的拖出去

代码语言:javascript
复制

#include <charconv>
#include <expected>
#include <string>
#include <system_error> 
#include <iostream>

std::expected<int, std::string> convertToInt(const std::string& input) {
    int value{};
    auto [ptr, ec] = std::from_chars(input.data(), input.data() + input.size(), value);
    
    if (ec == std::errc())
        return value;

    if (ec == std::errc::invalid_argument)
        return std::unexpected("Invalid number format");
    else if (ec == std::errc::result_out_of_range)
        return std::unexpected("Number out of range");

    return std::unexpected("Unknown conversion error");
}

int main() {
    std::string userInput = "111111111111111";

    auto result = convertToInt(userInput);
    if (result)
        std::cout << "Converted number: " << *result << '\n';
    else
        std::cout << "Error: " << result.error() << '\n';
}

c23有一种模拟的方法

代码语言:javascript
复制
#include <stdio.h>

struct { bool success; int value; } parse(const char* s)
{
    if (s == NULL)
       return (typeof(parse(0))) { false, 1};

    return (typeof(parse(0))) { true, 1 };
};

int main()
{
   auto r = parse("1");
   if (r.success) {
     printf("%d", r.value);
   }
}

不建议使用

LLVM 中的一致性分析框架详解 之 发散源和指令一致性判断 https://zhuanlan.zhihu.com/p/684983035

学点llvm

A story of a very large loop with a long instruction dependency chain https://johnnysswlab.com/a-story-of-a-very-large-loop-with-a-long-instruction-dependency-chain/

简单来说就是拆循环 loop fission + 降低数据buffur大小,小于l1 cacheline,提升性能

需要复现一下

如何发现是内存子系统的问题(buffer大于cacheline)? 使用likwid 查的。这个实验需要复现一下看看

When an instruction depends on the previous instruction depends on the previous instructions… : long instruction dependency chains and performance

简单来说就是通过 interleave 拆分任务,来加速,这个和loop fission还不太一样,loop fission就是单纯的拆循环,interleave又不同任务分发调度的感觉

Atomics And Concurrency

这个比较基础和cpprefence差不多 https://redixhumayun.github.io/systems/2024/01/03/atomics-and-concurrency.html

The Auto macro https://quuxplusone.github.io/blog/2018/08/11/the-auto-macro/
代码语言:javascript
复制
#pragma once

template<class L>
class AtScopeExit {
    L& m_lambda;
public:
    AtScopeExit(L& action) : m_lambda(action) {}
    ~AtScopeExit() noexcept(false) { m_lambda(); }
};

#define TOKEN_PASTEx(x, y) x ## y
#define TOKEN_PASTE(x, y) TOKEN_PASTEx(x, y)

#define Auto_INTERNAL1(lname, aname, ...) \
    auto lname = [&]() { __VA_ARGS__; }; \
    AtScopeExit<decltype(lname)> aname(lname);

#define Auto_INTERNAL2(ctr, ...) \
    Auto_INTERNAL1(TOKEN_PASTE(Auto_func_, ctr), \
        TOKEN_PASTE(Auto_instance_, ctr), __VA_ARGS__)

#define Auto(...) \
    Auto_INTERNAL2(__COUNTER__, __VA_ARGS__)

// 使用

bool Mutate(State *state){
    state->DisableLogging();
    Auto(state->EnableLogging());

    if (!state->AttemptOperation1()) return false;
    if (!state->AttemptOperation2()) return false;
    return true;
}
// 还能递归
void Example()
{
    Auto(
        puts("starting the first Auto");
        Auto(puts("cleaning up in the second Auto"));
        puts("getting ready to clean up in the first Auto");
    );
    puts("doing the main operation");
}
libfork https://arxiv.org/pdf/2402.18480.pdf

这个完成度看起来比taro强很多,且融合了很多taskflow点子

比如 https://tsung-wei-huang.github.io/papers/icpads20.pdf

文档 https://conorwilliams.github.io/libfork/api/schedule.html

代码 https://github.com/ConorWilliams/libfork

另外就是性能要测试一下,这里标记TODO有空测一下

开源项目介绍

  • • 一个unique ptr SSO优化实现 https://github.com/KRM7/small_unique_ptr 代码很短,600行,感觉可以讲一讲,这里标记一个TODO
  • • https://github.com/google/gemma.cpp 这是啥啊最近挺火的
  • • https://github.com/pizlonator/llvm-project-deluge 这个哥们fork llvm整了个safe c。看一乐
  • • https://github.com/TerensTare/modern_bloom 一个bloom filter实现
  • • https://github.com/catchorg/Catch2/commit/dc51386b9fd61f99ea9c660d01867e6ad489b403 幽默MSVC兼容性问题一例
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2024-03-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP每周推送 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 资讯
  • 文章
    • Rage Against The Glue: Beyond Run-Time Media Frameworks with Modern C++ https://cnrs.hal.science/hal-04090584/document
      • constexpr and consteval functions https://biowpn.github.io/bioweapon/2024/02/17/constexpr-consteval-function.html
        • How to debug C and C++ programs with rr https://developers.redhat.com/blog/2021/05/03/instant-replay-debugging-c-and-c-programs-with-rr#
          • Undefined behavior in C and C++ https://lumagraph.ie/undefined-behavior
            • Measuring energy usage: regular code vs. SIMD code https://lemire.me/blog/2024/02/19/measuring-energy-usage-regular-code-vs-simd-code/
              • My late discovery of std::filesystem - Part I https://www.sandordargo.com/blog/2024/02/28/std-filesystem-part1-paths-and-operations
                • How to write unit tests in C++ relying on non-code files? https://www.sandordargo.com/blog/2024/02/21/cpp-tests-with-resources
                  • Navigating Memory in C++: A Guide to Using std::uintptr_t for Address Handling https://blog.feabhas.com/2024/02/navigating-memory-in-c-a-guide-to-using-stduintptr_t-for-address-handling/
                    • Introduction To Low Latency Programming: Minimize Branching And Jumping https://tech.davidgorski.ca/introduction-to-low-latency-programming-minimize-branching-and-jumping/
                      • 1 << n vs. 1U << n and a cell phone autofocus problem https://rachelbythebay.com/w/2024/02/24/signext/
                        • 自底向上理解memory_order https://zhuanlan.zhihu.com/p/682286231
                          • Using std::expected from C++23 https://www.cppstories.com/2024/expected-cpp23/
                            • LLVM 中的一致性分析框架详解 之 发散源和指令一致性判断 https://zhuanlan.zhihu.com/p/684983035
                              • A story of a very large loop with a long instruction dependency chain https://johnnysswlab.com/a-story-of-a-very-large-loop-with-a-long-instruction-dependency-chain/
                                • When an instruction depends on the previous instruction depends on the previous instructions… : long instruction dependency chains and performance
                                  • Atomics And Concurrency
                                    • The Auto macro https://quuxplusone.github.io/blog/2018/08/11/the-auto-macro/
                                      • libfork https://arxiv.org/pdf/2402.18480.pdf
                                      • 开源项目介绍
                                      领券
                                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档