当前位置: 首页 > news >正文

跟我学C++中级篇——Concepts的循环依赖

一、循环依赖

循环依赖,这个东西非常可怕。如果是简单的依赖还好说,直接大家都可以看出来。但在复杂的场景下,如果产生这种循环依赖,很难发现,而且问题也可能比较隐藏,错误提示也不友好。
产生循环依赖的原因简单的说就是互相将彼此的任务完成当前自己任务完成的前提。从这个角度看,线程的死锁、类(头文件)、条件判断以及类似的场景都有可能产生循环依赖。不过相对于线程的死锁广泛流行为开发者熟知,条件判断可能太简单,基本很难有人写出这种低级错误,即使真写出来也很容易发现。
但是在C++编程中,模板编程相对于开发者们来说,本身就是一小众的场景,而对于概念这个C++20才推出的新特性可能更加用得少了。不过简单了解后会发现它其实也是一种条件约束机制,那么它有没有可能会发生循环依赖的情况呢?

二、Concepts的循环依赖

concepts产生循环依赖,一般是在有相当复杂度的模板编程设计中。如果不是特殊原因或者概念开发特别生疏的情况下,很难出现这种循环依赖。也正是因为产生的原因比较复杂,就越是让开发者难以解决,毕竟经验少么。
正常情况下的概念约束,不会复杂到约束太多个条件,但在一些模板库的开发中,可能由于设计的原因,导致多个模块中的概念线束产生依赖,特别是递推非线性循环依赖,非常隐蔽。另外比如模板参数中同时受多个概念的约束,而这些概念间又可能有互相约束的条件。
说得更直白一些,就好像一个人证明一个公式,这个公式的成立条件是A定理,A定理又依赖B定理,而B定理又依赖当前这个公式,这其实就是一种现实的“概念的循环依赖”。下面看一个简单的例子:

template<typename T>concept A=requires(T t){requires B<T>;// 依赖概念B};template<typename T>concept B=requires(T t){requires A<T>;// 依赖概念A};

三、如何解决

既然知道了概念有可能产生循环依赖,最简单的方法就是将概念本身约束在严格的范围内,不要动不动写出跨编译单元甚至模块的概念。这样除了可以尽量减少产生依赖的情况,即使真得出现依赖的情况,也容易发现和解决。但在一些场景下可能不可避免的会出现复杂的交互逻辑设计,那就需要设计要遵循下面的几种设计理念:

  1. 对复杂概念要进行更高层次的抽象
    将分层的设计引入到概念设计中,对同一类型的约束不要进行重复的多次概念约束,比如对同一个类的不同的属性约束,这时就可以抽象出一个更高的约束,统一进行管理
  2. 尽量减少概念的互相约束的可能性
    概念的约束尽量自耦合而与其约束解耦,也就是设计中的功能最小化原则
  3. 将复杂概念进行分解
    如果出现了复杂的概念,则首先考虑是不是可以将其分解成多个小的概念进行处理。如果无法拆解再考虑避免依赖

而在实际的开发中,如果已经出现了循环依赖的情况,除了利用上述的设计进行处理外,也可以使用一些编程的技巧的来处理:

  1. 前向声明
    前向声明是个宝。但需要知道的,Concepts本身并不支持前向声明,开发者只能通过对依赖的循环参数中的依赖通过前向声明打破这个依赖的链条,从而解决循环依赖。
// A.h#include"B.h"template<typename T>concept CheckB=requires(T t){t.bFunc();};class A{public:voidtestB(CheckBauto&b);// concept约束};// B.h#include"A.h"class B{public:A*testA();// ...};

解决方法:

// A.hclass B;class A{public:voidtestB(class B&b);};// B.hclass A;class B{public:A*testA();};// concepts.h 单独进行鲁出#include"B.h"template<typename T>concept CheckBfunc=requires(T t){t.bFunc();};

它其实就是普通的类依赖的例子,不过在模板编程中需要注意的前向声明有可能导致模板的ADL产生问题。
2. 使用延迟加载处理约束
在概念中可以使用Requirs子句来将约束的检查推迟到实例化时再进行处理

template<typename T>concept A=requires{// 延迟到实例化requiresrequires(T t){requires B<T>;};};template<typename T>concept B=requires{requiresrequires(T t){requires A<T>;};};

例程整体的比较简单,主要是说明方法。因为目前还没有真正的实际的工程中开发出或遇到相关的Concepts循环依赖的代码。

四、总结

总体上来看,一般来说从设计上就可以避免绝大多数的概念的循环依赖。可见,代码的编写其实最终拼的还是设计思想和设计理念。编程技巧只是在理念和思想下的一种闪光点而不能决定编程高度的基础。

http://www.jsqmd.com/news/373392/

相关文章:

  • 有了大模型不是要替代程序员,而是要求程序员掌握更多的知识。大模型本身是不存储对话内容的,对话内容要存储在 Redis 或其它数据库中。 大模型通过每次接收本次聊天所有对话内容,实现记忆功能。
  • 新手必看!4个免费公众号SVG排版技巧,让你的文章瞬间文艺范十足丨公众号svg制作工具 - peipei33
  • 2026年评价高的悬挂式除铁器/山东自卸式除铁器厂家选择参考建议 - 品牌宣传支持者
  • 2026年重庆石英砂服务商排名,重庆荣顺矿产品有限公司靠谱吗 - 工业推荐榜
  • 大模型给智能体提供了一个大脑,一个完整的智能体还需要灵魂、记忆、手脚。程序员要做的,就是开发灵魂、记忆、手脚。所以不要整天悲观的认为 AI 将要取代程序员,网上的段子,听听就行。评价一下这个观点。
  • 【信号处理】(高斯分布)最大熵定理 - 教程
  • 2026年知名的冷热流道精密模具/五轴加工精密模具值得信赖厂家推荐(精选) - 品牌宣传支持者
  • 2026舟山长乔海洋公园体验超棒,市场口碑如何? - 工业品网
  • 5.5 小结 函数调用最佳实践与常见坑
  • 2026合肥儿童摄影口碑排名TOP5|家长必看的专业推荐 - 提酒换清欢
  • 6.1 ReAct再复习 思考行动观察直到任务完成
  • 2026年热门的强磁磁选机/滚筒磁选机全方位厂家推荐参考 - 品牌宣传支持者
  • 一次ssh无法连接服务器故障处理报告 - wanghongwei
  • 5.4 用ChatCompletion API做Tool Calls 和Assistants有啥区别
  • 2026合肥儿童摄影推荐:儿童摄影标杆‖红黄蓝品牌实力与服务全维度解读 - 提酒换清欢
  • 智慧公厕哪家质量好? - 博客湾
  • 2026年知名的尼龙扎带/防滑尼龙扎带厂家综合实力参考(2025) - 品牌宣传支持者
  • clickhouse和pgSql跨库查询方案对比 - 实践
  • 5.3 用Assistants API实现多轮Function Calling
  • 2026年正规江南汽车/湖北江南专用汽车推荐几家可靠供应商参考 - 品牌宣传支持者
  • **解锁Agent智能体新纪元:自主协作、任务分解与人类意图对齐的终极指南**
  • 手持式雷达流速仪水文雷达测速仪
  • 智慧公厕哪家可靠? - 博客湾
  • 对比一圈后!更贴合专科生的降AIGC平台 千笔·专业降AI率智能体 VS 文途AI
  • 输入新老客户获客成本与复购,计算新客户生命周期价值更高。
  • 并行编程实战——CUDA编程的并行前缀和
  • 2026年热门的烤漆视觉点胶机/喷射阀视觉点胶机值得信赖厂家推荐(精选) - 品牌宣传支持者
  • 2026年靠谱的塑料金属分离器厂家选购攻略与推荐 - 品牌鉴赏师
  • 科研党收藏!更贴合专科生的降AIGC软件 千笔·专业降AI率智能体 VS 灵感ai
  • 导师推荐!AI论文软件 千笔·专业学术智能体 VS 知文AI,自考写作文首选