公众号
qq群 点击进入
欢迎投稿,推荐或自荐文章/软件/资源等
请提交 issue 或评论区留言
本期文章由 黄亮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
另外clang gcc有单独的工具,比如ftime-trace,比如 这个
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
音视频领域有个 M x N问题
不同的media processors 在N种平台上导致api复杂度上升不可维护
考虑一种接口设计方法,让代码更简练
琢磨半天结果是concept + boost pfr之类的检测接口/策略模版
还有一些其他的想法 在这里
记住这段代码就行了
// 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最好两种分支都实现,避免意外的问题
其实rr和gdb record差不多,感觉可以用这个文档例子做个视频,这里标记一个TODO
讲UB产生的场景,以及如何避免,给的方案编译flag ubsan以及换个语言,我谢谢你
lemire新活,只要你的代码足够快,即使是simd这种费电的指令相比而言整体费电也不多
值得复现一下
介绍fs相关api,比如遍历之类的,我就不列出来了
介绍非代码文件怎么和代码编译到一起的,bazel/cmake都有类似configfile的方法。embed赶紧来吧
为什么用它,用int32 int64之类的类型,reinterpret cast可能会有fpermissive报错,比如
#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就没问题
#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更合适
哥们出书了,120页卖10刀有点贵我靠,书在这里 https://a.co/d/0U6KOfb
这个文章是节选,大概思路就是降低跳转和分支
勤用 && | 利用短路特性 |
[[gnu::always_inline]]
备注
cmov 描述不对,if简单赋值也能生成cmov, cmov是一个值得展开的话题
variant + visit开销部份场景要比虚函数要好,不要因噎废食
感谢 球猫 Anien 指正
一个样例sss
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;
}
}
#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
非常幽默
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并没有这个问题
理解理解
不会的拖出去
#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有一种模拟的方法
#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
简单来说就是拆循环 loop fission + 降低数据buffur大小,小于l1 cacheline,提升性能
需要复现一下
如何发现是内存子系统的问题(buffer大于cacheline)? 使用likwid 查的。这个实验需要复现一下看看
简单来说就是通过 interleave 拆分任务,来加速,这个和loop fission还不太一样,loop fission就是单纯的拆循环,interleave又不同任务分发调度的感觉
这个比较基础和cpprefence差不多
#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");
}
这个完成度看起来比taro强很多,且融合了很多taskflow点子
另外就是性能要测试一下,这里标记TODO有空测一下