文章
- 那些编译器优化盲区 - 1
值得一看,介绍了很多边角优化点。其中无符号判断empty和pointer alias这些我们在之前介绍过。值得再看
- 【线上问题】P1级公司故障,年终奖不保
bug的代码长这样
代码语言:javascript复制void AdSort(std::vector<AdItem> &ad_items) {
std::sort(ad_items.begin(), ad_items.end(), [](const AdItem &item1, const AdItem &item2) {
if (item1.priority < item2.priority) {
return true;
} else if (item1.priority > item2.priority) {
return false;
}
return item1.score >= item2.score;
} );
}
注意比较要求严格弱序,所以这里的lambda实现有问题
等于应该返回false
这个问题其实算是老生常谈了,搜std::sort coredump能搜到好几个std::sort代码走读/科普严格弱序啥意思的文章。这里就不啰嗦了
- The Evolutions of Lambdas in C 14, C 17 and C 20
这些年来c lambda的变化
c 14
代码语言:javascript复制//默认值
auto myLambda1 = [](int x, int y = 0){ std::cout << x << '-' << y << 'n'; };
// 自动推导参数(残废的模版)
auto myLambda = [](auto&& x){ std::cout << x << 'n'; };
//返回一个lambda
auto getMyLambda(int z)
{
return [z](int x)
{
// ...
// ...
// ...
};
}
void f()
{
// ...
int z = 42;
auto myLambda = getMyLambda(z);
// ...
}
c 17
代码语言:javascript复制constexpr auto times2 = [] (int n) { return n * 2; };
//拷贝this
struct MyType
{
int m_value;
auto getLambda()
{
return [self = *this](){ return self.m_value; };
}
};
c 20
代码语言:javascript复制// 模版
auto myLambda = []<typename T>(T&& value){ std::cout << value << 'n'; };
//变参模版
template<typename... Ts>
void f(Ts&&... args)
{
auto myLambda = [...args = std::forward<Ts>(args)](){};
}
- c tip of week Did you know that static reflection proposal for C 2X has mirror/value based interface?
这个提案看个乐,未必能过
代码语言:javascript复制template <class T> auto to_string() {
const auto t = get_aliased(mirror(T));
std::stringstream str{};
str << get_name(t) << '{';
for_each(get_enumerators(t),
[&str](auto o) { str << get_name(o) << '=' << get_constant(o) << ';'; }
);
str << '}';
return str.str();
}
enum Weekdays {
Mon = 2,
Tue = 3,
Wed = 4,
Thu = 5,
Fri = 6,
Sat = 1,
Sun = 0
};
int main() {
std::cout << to_string<Weekdays>(); // prints Weekdays{Mon=2;Tue=3;Wed=4;Thu=5;Fri=6;Sat=1;Sun=0;}
}
- Little C Standard Library Utility: std::align
通过这个小工具可以轻松写出自己的allocator的aligned_alloc接口
面向的需求是,自定义的一个分配器(比如固定的buffer cache,构造/析构 不释放)可能需要提供alloc还有aligned_alloc
而aligned_alloc很麻烦,要考虑挺多对齐相关的事儿
视频
- C Weekly - Ep 302 - It’s Not Complicated, It’s std::complex
介绍std::complex
- Tina Ulbrich - How to rangify your code - Meeting C 2021
介绍他们使用range的经验,实践就是干掉所有for循环,能用range的用range替代
- Walter E. Brown - Correctly calculating min, max and more - Meeting C online
这个大爷的口音真的很让人犯困,但是这个问题可能很多人没注意 min max 在等于的场景下的语意很模糊
一个简单的实现
代码语言:javascript复制template<typename T>
const T& min(const T& a, const T& b) {
return a < b ? a : b;
}
template<typename T>
const T& max(const T& a, const T& b) {
return a > b ? a : b;
}
如果a等于b ,返回的是b
也许你会说,这又咋了,返回a 返回b有啥区别呢?简单int之类scalar type的确实没啥区别
给个例子
代码语言:javascript复制struct student {
std::string name;
int id;
inline static int regist = 0;
student(std::string n) : name(n), id(regist ) {}
bool operator <(student s) const {
return name < s.name;
}
}
如果比较student 哪个小 明明student a b 的id绝对是不同的,但是永远返回了b,区分不清 a b的场景,
那如果求最大值,是不是应该返回a,这样才能区分
这就是这个两个接口的问题
行为要互补
另外,需要对比较的对象做一个约束(concept)一直递增,这样就能更好的描述这两个接口
所以实现就这个样子
代码语言:javascript复制inline bool out_of_order(... a, ... b) { return b<a;}
template<typename T>
const T& min(const T& a, const T& b) {
return out_of_order(a, b) ? b : a;
}
template<typename T>
const T& max(const T& a, const T& b) {
return out_of_order(a, b) ? a : b;
}
引申一下,这个约束叫啥呢?严格全序? 引入std::range::less
这个视频非常值得一看,把compare讲的明明白白
项目
- parlaylib并行算法工具箱
- mold 发布正式版1.0,之前我们介绍过,是一个非常牛的 linker,速度快
- cpp-rrb 一个RRB-tree实现,尽管 immer.库有个类似的immer::flex_vector
- TLM 一个检测线程死锁的库
一个简单例子
代码语言:javascript复制#include "thread_monitor/thread_monitor.h"
void myLivelockedMethod();
void myParentMethod() {
thread_monitor::ThreadMonitor<> monitor("Livelock demo", 1);
std::this_thread::sleep_for(2ms);
thread_monitor::threadMonitorCheckpoint(2);
myLivelockedMethod();
}
void myLivelockedMethod() {
thread_monitor::threadMonitorCheckpoint(3);
while (true) {
std::this_thread::sleep_for(1ms);
}
}
明显的死循环,过一段时间,monitor就会吧这个打印出来
代码语言:javascript复制Frozen thread: Livelock demo id: 140085845083904
Checkpoint: 1 at: 2021-12-09 23:29:36.201542 delta: 0 us
Checkpoint: 2 at: 2021-12-09 23:29:36.203625 delta: 2083 us
原理就是有个队列记录状态,状态长时间不更新就打印
如果你把thread_monitor::threadMonitorCheckpoint(4);
放到while循环内部,就永远不会触发frozen打印
用来做个debug还是够用的
- libtree
将ldd的显示列成tree的形式