CITP——更适合约束接口的CRTP变式 - CLimber

news/2025/11/7 22:06:42/文章来源:https://www.cnblogs.com/climber-rong/p/19201005

CITP设计文档

摘要

在C++中,前人已经提出了多种约束接口的方式。其中,CRTP不妨是一个适用于低标准且不需要性能的静态多态设计方式。但CRTP无法约束构造函数,实现过程涉及静态转换,代码复杂。为此,我们提出了CRTP的变式——CITPCuriously Iterating Template Pattern,奇异递推模板模式),并将其首次应用到Stamon当中。

需求性分析

我们先来引入一段典型的CRTP设计:

/* 例1 */
#include <iostream>
using namespace std;template<class Impl>
class Constraint {public:int square(int x) {// 被开发者调用的接口return static_cast<Impl*>(this)->square(x);// 静态转换为Implementation,并调用其实现,实现接口约束}
};class Implementation : public Constraint<Implementation> {public:int square(int x) {// Constraint::f(int)的实现return x*x;}
};using Square = Implementation;int main()
{Square s;cout<< s.square(5) <<endl;    // 运行结果:25return 0;
}

以上设计存在以下缺陷:

  • 使用特殊的模板递归形式,学习成本高,难以理解
  • 将this静态转换为子类并调用,实现复杂
  • 无法安全地对构造函数进行约束

导致以上缺陷的原因如下:

  • 用父类约束子类,又将子类作为类型参数传递给父类,产生奇异递归
  • 在父类中调用子类的成员,需要进行静态转换
  • 构造函数一般自底而上调用,因此父类无法简便地约束构造函数

在经过大量地实验性设计后,我们综合了代理模式等设计模式,提出了一种可以解决以上缺陷的方案:与CRTP将用于接口约束的类作为父类的做法相反,我们将用于接口约束的类作为子类,受约束的类作为父类,从而让接口约束从递归变为递推。

这种方案具有以下优点:

  • 不需要复杂的递归形式
  • 让受约束的父类被子类调用,鉴于子类可以安全调用父类成员,用于约束的类无需静态转换
  • 用于约束的子类在构造时可以将构造函数完美转发给受约束的父类

综上所述,在某些情景下,CITP能比CRTP约束更多东西,且能减少思维量。

设计

我们来看看 例1 在CITP中的设计:

/* 例2 */
#include <iostream>
using namespace std;class Implementation {// 实现类作为父类受约束public:int square(int x) {// 受约束接口return x*x;}
};template<class Impl>
class Constraint : public Impl {// 用于约束的类作为子类,继承实现类public:int square(int x) {// 调用Impl的实现return Impl::square(x);}
};using Square = Constraint<Implementation>;
// 将Implementation传递给Constraint作为约束int main()
{Square s;cout<< s.square(5) <<endl;    // 运行结果:25return 0;
}

例2 中,我们将Constraint作为一个模板类,并使其继承模板提供的类,因此Constraint可以完美的调用其父类(即受约束的类)的成员,包括构造函数。开发者在实现时应使用using关键字给Constraint赋予供用户使用的别名(例如 例2 的Square)。

我们再看看在CITP中,如何约束构造函数:

/* 例3 */
#include <iostream>
using namespace std;class Implementation {// 实现类作为父类受约束int k, b;public:Implementation(int K, int B) : k(K), b(B) {};int f(int x) {// 受约束接口return k*x + b;}
};template<class Impl>
class Constraint : public Impl {// 用于约束的类作为子类,继承实现类public:Constraint(int K, int B) : Impl(K,B) {};int f(int x) {// 调用Impl的实现return Impl::f(x);}
};using Linear = Constraint<Implementation>;
// 将Implementation传递给Constraint作为约束int main()
{Linear l(4,5);cout<< l.f(5) <<endl;    // 运行结果:25return 0;
}

可以看到,Constraint只需要正常编写构造函数,并转发给父类的构造函数,即可实现构造函数的约束。此外,由于析构函数的调用顺序是从子类到父类,因此Constraint哪怕没有编写析构函数,Implementation的析构函数也照样会被正常调用。但这也使得析构函数无法收到约束——CITP难以保证受约束的类一定拥有开发者手写的析构函数。

CITP的设计中,约束重载运算符的方式和约束普通方法的方式是不同的。我们将 例3 中的函数int f(int)改装成int operator<<(int),来看看CITP是如何约束重载运算符的:

/* 例4 */
#include <iostream>
using namespace std;class Implementation {// 实现类作为父类受约束int k, b;public:Implementation(int K, int B) : k(K), b(B) {};int operator<<(int x) {// 受约束接口return k*x + b;}
};template<class Impl>
class Constraint : public Impl {// 用于约束的类作为子类,继承实现类public:Constraint(int K, int B) : Impl(K,B) {};int operator<<(int x) {// 调用Impl的实现return Impl::operator<<(x);}
};using Linear = Constraint<Implementation>;
// 将Implementation传递给Constraint作为约束int main()
{Linear l(4,5);cout<< (l<<5) <<endl;    // 运行结果:25return 0;
}

结论

CITP相较于CRTP,更专注于接口约束,是一个适用于低C++标准的高性能方案。但CITP目前仍然存在缺陷:

  • 无法具体约束函数的行为,也无法约束析构函数
  • 在传递参数、返回值时也可能发生参数、返回值的隐式转换且无法约束这种转换
  • 如果CITP模板代码处于未使用状态,编译器可能不会进行接口约束检查

这些问题正在研究当中,有待解决。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/959217.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

函数的可变参数传参

一.前言 可变参数传参是C语言的一种高级用法。二. 用法示例 求任意个 int 类型数据的平均值。点击查看代码 double avg_int(int count, ...) {va_list ap; /* 2. 声明参数列表变量 */int sum = 0;va…

P12366 [蓝桥杯 2022 省 Python B] 数位排序

将数字与数位和捆绑(使用结构体或元组)放入数组或列表,以数位和为关键字排序,最后输出第 m 个数。 #include<stdio.h> #include<algorithm> using namespace std; const int MAXN=1e6+7; struct Node{…

重组蛋白表达技术|HEK293细胞蛋白表达|高效重组蛋白生产服务

一、表达系统的技术特性与选择策略 哺乳动物细胞表达系统以其卓越的翻译后修饰能力成为复杂蛋白表达的首选方案。其中,HEK293细胞凭借高转染效率和快速生长特性,在瞬时表达中表现优异;而CHO细胞则因其在悬浮培养中的…

CJI8运行查询没有数据

CJI8运行查询没有数据,发现不是权限问题,是因为查询界面设置的问题。如下: To view the entire transfer in CJI8, the report must be executed for Overall values without the year. ☆ No matter how much you …

Para 集训

Para 给我推的高质量题目,终于是找时间整理出来了。Para 好闪,拜谢 Para!Para 最好啦! [清华集训 2014] 主旋律 abs,第一题就忘了怎么做了。 DAG 计数模板题。 这里有一个经典的 trick:不是强连通分量的总会存在…

RK3576在智能工程机械中的应用|三屏八摄AI视觉解决方案

一、工程机械智能化的加速趋势近年来,随着人工智能与边缘计算的深入融合,工程机械行业正迎来从“机械化”到“智能化”的转型浪潮。无论是挖掘机、装载机、塔吊,还是矿卡、摊铺机等重型设备,智能控制、实时监控与人…

贪心,排序,二分,分治

题目描述 马上就要放暑假啦! 为了激励一下公司的员工,徐老师决定给所有人发奖金! 发奖金的方式非常简单,徐老师会在桌上一字排开 \(n\) 张纸团,每张纸团上会写着一个数字 \(a_i\),为了平衡公司成本,这里的数字可…

python01

练习编程语言:是我们与计算机交流的介质 编程:用编程语言写出一个个文件,最后达到我们的目的 编程有什么用:让计算机来帮我们干活 因为了解清楚才能学好所以引出下面的内容。 计算机组成原理 控制器 类似于大脑来控…

C语言实现数据结构顺序表

1.顺序表的定义 线性表可分为两种存储结构,一种是顺序存储结构,一种是链式存储结构。一般来说,顺序表是一个相同数据类型的集合,且内存地址一定相邻。在C语言中,一般使用数组实现。 2.顺序表的存储结构 使用结构体…

AI Compass前沿速览:Cursor 2.0、Firefly Image5、Agent HQ 、LongCat-Video、Kimi-k2 Thinking

AI Compass前沿速览:Cursor 2.0、Firefly Image5、Agent HQ 、LongCat-Video、Kimi-k2 ThinkingAI Compass前沿速览:Cursor 2.0、Firefly Image5、Agent HQ 、LongCat-Video、Kimi-k2 Thinking AI-Compass 致力于构建…

25.11.7联考题解

A 简单题,考虑一个串变化后不同并且计数不重不漏只须保证区间两端不同即可。 B 简单贪心。shopping plans 的超级弱化版。 C 设 \(f_i\) 表示被分在 \(\le i\) 的 L 型的方案数,显然有 \(f_i=\left(\sum_{j=x-i}^{x-…

浅谈dp中的最优化、计数问题

前言 诚然,这东西本来是一个挺好的东西的,但是如果它染上了数学,那么就不那么好了。 我承认,我的分类和题目选取是不够全面、不够有代表性的,因为这只是写给我自己看的。 这东西有三个难点:状态,转移,优化。(…

CF715B

给定 \(n\) 个点 \(m\) 条边的无向图,以及 \(s, t, L\)。每条边有边权(有些被抹去),你要为每个被抹去的边权赋一个正整数值使得 \(s \rightarrow t\) 的最短路为 \(L\)。 \(n, m \le 10^5,L \le 10^9\)首先把所有未…

[NOIP 2001 提高组] 一元三次方程求解

看题目数据范围: 方程存在三个不同实根(根的范围在 −100 至 100 之间) 可以知道这道题其实可以暴力 #include <iostream> #include <cstdio> using namespace std; int main() {double a,b,c,d;scanf(&…

EPnP算法学习随笔

EPnP算法学习随笔这几天刚好在看epnp算法,写篇随笔简要回顾一下。 PnP问题是个很经典的问题,就是根据图像上的关键点来估计相机的位姿,这里主要研究的是单目摄像机,但是值的注意的是单目的精度一般都比较差,因为单…

毒盘未转存仅支持在线观看30s

毒盘未转存仅支持在线观看30s转载,原作者不详 解决方案:控制台里面输入这些代码,回车。 let video = document.querySelectorAll("#html5player_html5_api")[0] video.controls="true" video.p…

Advantech iView SQL注入漏洞分析:认证绕过与数据泄露

本文详细分析了CVE-2022-50594漏洞,涉及Advantech iView SNMP管理工具中的SQL注入漏洞,攻击者可绕过认证窃取包括明文密码在内的用户数据,CVSS评分8.8分。概述 CVE-2022-50594是Advantech iView软件中存在的一个高危…

【机器学习入门】7.1 决策树 —— 像 “判断流程图” 一样做分类 - 教程

【机器学习入门】7.1 决策树 —— 像 “判断流程图” 一样做分类 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: …

P14322 「ALFR Round 11」E 空崎ヒナ 小结

首先把 x 移个项,变成 abs(b[i]-x)。 然后你发现这个东西就是 max a_i 的倍数了。 这个东西很好写,首先你先预处理单调栈和后缀答案。 后缀答案不能在线,于是离线处理。 然后你发现回答询问也不能在线。 于是你再离…