C 动态新闻推送 第52期
从reddit/hackernews/lobsters/meetingcpp摘抄一些c 动态
文章
- Curious lack of sprintf scaling
数字转字符串 sprintf性能,非常垃圾,使用fm
t或者std::to_chars
- Did you know wrapping an unqualified function name in parentheses suppresses argument-dependent lookup?
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?
#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?
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