关于程序员内功
笔者认为的程序员内功包括:设计原则和设计模式的深入理解与实践、至少一门编程语言的深入应用(基础应用算外功)、算法与数据结构(笔者以前是ACM金牌选手,有本出版夭折的算法书,心累所以公众号里不一定分享相关文章)、性能、容灾等。笔者还在修炼中,以后想到其它合适的内容再继续补充到程序喵内功修炼
列表里[狗头]。
导语
分享一种笔者工作中常常用到的迭代器模式的应用(基于C++迭代器又包了一层用于封装一些东西的情况下遍历操作另外一些东西)。 这里是借助std::function_ref实现foreach来遍历封装的容器里元素的子结构。
背景与前提
1. 背景
用户类希望遍历封装的容器里元素的子结构,并且只认识子结构,不认识元素的结构,遵循最少知识原则(迪米特法则)。
2. 前提
比如有一个结构A,包含了x、y、z三个子结构
message A {
X x = 1;
Y y = 2;
Z z = 3;
}
然后如下a_manager管理了A的聚合many_a_
class a_manager {
......
private:
// Container指代std::vector、std::map等容器
Container<std::shared_ptr<A>> many_a_;
};
目标
希望在某些时候可以批量更新子结构z里的数据,并且不需要知道A以及x和y的存在,只知道a_manager(遵循最少知识原则)。
解决
实现foreach,然后把用户”批量修改子结构z“的逻辑写成lambda或者函数,然后通过std::function_ref(详见https://en.cppreference.com/w/cpp/utility/functional/function_ref)传给foreach。看了代码你就明白了
// 给a_manager新增一个publish接口
int32_t a_manager::foreach_z(
std::function_ref<int32_t(Z&)> callback) {
for (auto& a : many_a_) {
if (!a.second) {
continue;
}
int32_t ret = callback(*(a.second->mutable_z()));
if(ret < 0){
return ret;
}
}
return 0;
}
用户类B使用的时候
void B::fix_z(){
int32_t ret = get_a_manager().foreach_z([](Z& z) -> int32_t {
......
return 0;
});
}
总结
迭代器(iterator)模式分离了聚合对象和对聚合对象的遍历行为,这样既可以做到不暴露集合内部结构和需要封装的数据,又可以让外部代码透明的访问集合内部允许访问的数据。 而这里借助std::function_ref实现foreach来遍历封装的容器里元素的子结构则是迭代器模式的一种应用。
关于
本博所有文章均为博主原创,未经许可不得转载。
https://www.prolightsfxjh.com/article/iterator-and-foreach/
Thank you!
------from ProLightsfx
如果你对推荐系统、游戏开发、C++优化、程序员内功等感兴趣或者想参与讨论的话,欢迎关注笔者公众号.
非特殊说明,本博所有文章均为博主原创,未经许可不得转载。
如经许可后转载,请注明出处:https://prolightsfxjh.com/article/iterator-and-foreach/
共有 0 条评论