首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

如何递归地继承模板类本身?(不是CRTP!)

递归地继承模板类本身可以通过模板元编程中的递归模板实现。下面是一个示例代码:

代码语言:txt
复制
template <typename T>
class RecursiveTemplate {
public:
    // 递归终止条件
    void foo() {
        // 实现递归终止条件的逻辑
    }
};

template <typename T>
class RecursiveTemplate<T> : public RecursiveTemplate<T-1> {
public:
    // 递归继承模板类本身
    void foo() {
        // 实现递归继承的逻辑
        RecursiveTemplate<T-1>::foo();
    }
};

在上述示例中,通过模板类的特化来实现递归继承。递归终止条件是模板参数为某个特定值时,不再继续递归。递归继承的过程中,每一层都会调用上一层的成员函数,实现递归的效果。

递归地继承模板类本身的优势在于可以实现更加灵活和复杂的类结构,满足不同的需求。应用场景包括但不限于:模板元编程、泛型编程、递归数据结构等。

腾讯云相关产品中,与递归地继承模板类本身相关的产品和服务可能包括云函数(Serverless)、云数据库(CDB)、云存储(COS)等。具体推荐的产品和产品介绍链接地址可以参考腾讯云官方文档或咨询腾讯云客服。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++雾中风景14:CRTP, 模板的黑魔法

CRTP,奇特的递归模板模式 (Curiously Recurring Template Pattern) 是 C++ 的一种看起来很怪异的模板编程技巧。...std::enable_shared_from_this,并且自己是作为模板参数传递给父的。...这就给让代码看起来有些"唬人",看起来像是继承自己一样。但其实呢?这里只是用到了模板派生,让父能够在编译器感知到子类的模板存在,二者不是真正意义上的继承关系。...当然这种“奇技淫巧”并不是用来装逼的。所以本节笔者就结合自己本身的实践,来描述一下CRTP应该如何在实际的编码场景之中使用,以及能够解决一些什么样的问题。...Doris之中应用了CRTP来实现颠倒继承的目的。 颠倒继承(Upside Down Inheritance),顾名思义就是通过父向子类添加功能。因为它的效果与普通继承父到子的逻辑是相反的。

1.6K32
  • 惯用法之CRTP

    概念 CRTP是Curiously Recurring Template Pattern的缩写,中文译为奇异的递归模板模式,是由James O. Coplien在其1995年的论文中首次提出。...其实,这样做的目的其实很明确,从基对象的角度来看,派生对象其实就是本身,这样的话只需要使用类型转换就可以把基转化成派生,从而实现基对象对派生对象的访问。...截止到此,我们对CRTP有了一个初步的认识,总结起来,其有以下两个特点: • 继承模板 • 派生将自身作为参数传给模板 颠倒继承 仍然使用上一节中的例子,如下: template <typename...而对于普通继承,则是派生中调用基的成员函数,扩展了派生的功能,这就是我们所说的颠倒继承。 使用场景 俗话说,存在即合理。既然有CRTP,那么其必然有自己存在的道理。...但是,问题在于Base实际上是一个模板,而不是一个实际的。因此,如果存在名为Derived和Derived1的派生,则基模板初始化将具有不同的类型。

    81820

    C++模版的本质

    首先C++是可以提供OOP(面向对象)范式编程的语言,所以支持概念,本身就是现实中一事物的抽象,包括状态和对应的操作,打个比喻,大多数情况下我们谈论汽车,并不是指具体某辆汽车,而是某一汽车(某个品牌...模板特化 模板特化为了支持模板或者模板函数在特定的情况(指明模板的部分参数(偏特化)或者全部参数(完全特化))下特殊实现和优化,而这个机制给与模板某些高阶功能提供了基础,比如模板递归(提供递归终止条件实现...通过把不同策略设计成独立的,然后通过模板参数对主进行配置,通常policy-base class design采用继承方式去实现,这要求每个策略在设计的时候要相互独立正交。...模板多个实例很有可能会隐式增加二进制文件的大小等,所以模板在某些情况下有一定代价,一定要在擅长的地方发挥才能; 如何降低门槛,对初学者更友好,如何降低复杂性,这个是C++未来发展重要的方向。...模板本身是图灵完备的,所以可以结合C++其他特性,编译期常量和常量表达式,编译期计算,继承,友元friend等开阔出更多优雅的设计,比如元容器,类型擦除,自省和反射(静态反射和metaclass)等,将来会出现更多优秀的设计

    1.7K30

    经典永不过时!重温设计模式

    尽量让每个或者函数只负责软件中的一个功能,这条原则的主要目的是减少复杂度,你不需要费尽心机去构思如何仅用200 行代码来实现复杂设计,实际上完全可以使用十几个清晰的方法,这里核心是: 通过实现最基本...CRTP -The curiously recurring template pattern CRTP (奇异递归模板模式)是一种在编译期实现多态方法,是对运行时多态一种优化,多态是个很好的特性,但是动态绑定比较慢...而使用 CRTP,完全消除了动态绑定,降低了继承带来的虚函数表查询开销。...CRTP包含: 从模板继承, 使用派生本身作为基模板参数。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 这样做的目的是在基中使用派生。...从基础对象的角度来看,派生对象本身就是对象,但是是向下转换的对象。因此,基可以通过将static_cast自身放入派生来访问派生.

    1.2K40

    醒醒吧,静态多态根本没有这么香

    CRTP CRTP 全称 Curiously Recurring Template Pattern,即奇异递归模板模式,是一种经典的 C++ 设计模式,听起来很反人类,我们先来看一段代码: #include...char* argv[]) { Child1 child1; Child2 child2; Print(child1); Print(child2); } 这是一个 CRTP...的典型使用场景 —— 静态多态,其实很容易理解,如果需要在编译期让父的某个方法调用子类的方法,那必然需要让父能够感知到子类的类型信息,因为你需要将 this 指针转换成子类指针才能调用对应方法。...很明显是因为虽然 Child1 和 Child2 同源自 Bsae,但实际上他俩的基完全是不同类型!...其实这一特点单单影响方法还好,模板方法不嫌多,但是如果我想要使用静态多态实现的有多层继承关系呢?

    62610

    【从零开始学深度学习编译器】十八,MLIR中的Interfaces

    因此,我们要明确Interface并不是Operation的核心,而是一些通用变换的核心。在【从零开始学深度学习编译器】十三,如何在MLIR里面写Pass?...Dialect Interface可以通过继承一个CRTPDialectInterfaceBase::Base来进行定义。...CRTP的介绍可以参考:https://zh.wikipedia.org/wiki/奇异递归模板模式,我理解静态多态(CRTP)是因为MLIR里面会存在很多Dialect Interface要从这个DialectInterfaceBase...这些将定义Concept和Model的 Traits 作为模板参数。这些提供了基于概念的多态性的实现,其中Concept定义了一组虚方法,这些方法被在具体实体类型上模板化的Model覆盖。...例如: /// 具体的外部Interface实现。 这不需要修改类型本身的定义。

    1.9K20

    编程轻松炫技:不费吹灰之力打印100个数字,面试考点应有尽有

    今天来给大家用一些C++的骚操作来写出这种代码,欢迎留言与转发~ 这道题目其实非常简单,但却涵盖了很多面试考点,其中包括: 模版特化、便特化,如何编写递归模版 CRTP std::copy、std::iota...、std::transform如何使用,各自算法实现 静态变量 等等 1.递归 1-100可以拆为554,用三个函数去打印它,函数a cout一次,然后变量加1,函数b层层嵌套a重复5次,函数c层层嵌套...JustPrint { JustPrint() { std::cout << 1 << " "; } }; int main() { JustPrint j; } 3.CRTP...方式3基于方式2,将其改造为crtp编程风格,是不是有点看不懂了,嘿嘿。...其实就是两个,第一个Print为父,打印每次的I,并调用子类,子类PrintDerived即成Print,并将自己传递给父,子类是一个重载,控制递归终止。

    14810

    【笔记】《Effective C++》条款26-55

    例如stack默认由deque实现, 但是stack并不属于deque, 只是依据在deque上而已) 39 明智而审慎使用private继承 由于访问限制的原因, 编译器无法自动将private继承的派生转型为基...(empty base optimization)的原因不会占用额外的字节 40 明智而审慎使用多重继承 多重继承可能会导致很多歧义, 例如要调用两个基都有的同名函数时, 需要进行匹配性计算, 这个匹配计算与函数的访问性无关...41 了解隐式接口和编译期多态 普通编程的时候一个所需的都是显式接口(头文件声明的接口)和运行期多态(继承而来的接口), 多数都是我们可控的 模板编程的时候我们看不到模板参数具体的头文件声明(因为模板参数本身是未定的...称为成员函数模板(member function template) 智能指针编写了非explicit的构造函数, 在自身底层是T类型的指针时, 接受一个U类型的指针作为构造函数的参数, 然后通过原始指针本身的转换和继承形式将...这种写法称为"怪异的循环模板模式"(CRTP): 有些旧版本的new函数会使用std::nothrow版本的, 分配失败的时候会返回null指针.

    91830

    访问私有成员——从技术实现的角度破坏封装 性

    编码习惯也严格按照相应的规则,该封装的时候进行封装,该继承的时候进行继承,以使得编程思维从之前的面向过程逐步过渡到面向对象。...specialization, but will be checked when substituting into the partial specialization. — end note ] 也就是说模板参数可以是某个的私有类型...,其模板参数为int A::*Member,功能是返回A中的成员变量,编译后,报错如下: test.cc: 在函数‘int main()’中: test.cc:7:15: 错误:‘int A::data...,下面将介绍一种方式,其在不修改本身定义的情况下实现访问私有成员变量。...2、以&A::data_作为模板参数,对模板PtrTaker进行显示实例化,在显示实例化的时候,虽然不创建对象,但是对于其中存在的静态变量依然会进行初始化。

    22830

    this类型_TypeScript笔记11

    没错,这种JavaScript运行时特性,在TypeScript静态类型系统中同样支持 具体,TypeScript中的this类型分为2: class this type:/接口(的成员方法)中的...我们知道运行时this指向当前或其子类实例,这在JavaScript运行时是一种非常常见的行为 也就是说,this的类型并不是固定的,取决于其调用上下文,例如: // A实例类型 new A().foo...),那么,应该如何描述this的类型?...this既是B实例也是A实例,姑且认为bar(): B & A是合适的,但无论如何foo(): A & B是不合理的,因为基实例并不一定是子类实例……我们似乎没有办法给this标出一个合适的类型,...具体的,this类型在实现上相当于A>(即经典的CRTP 奇异递归模板模式),中this值的类型就是泛型参数this。

    70420

    深入理解PHP高级技巧、面向对象与核心技术

    一、高级PHP技巧 A.多维数组 1.自定义排序 B.高级函数定义 1.递归函数:函数自己调用自己的行为;递归需要一个退出语句;需要注意资源消耗; 2.静态变量让函数在多次被调用时记住变量的值,而这些变量并不是全局变量...1.抽象是父模板。...通过定义一个抽象,我们可以指明的一般行为。换句话说一个抽象定义了接口:这个基继承如何被使用。然后子类会负责定义这些接口的真正的实现。...抽象和它的继承之间是“是一个”(is a)的关系,接口和它的继承之间是一个“有相同的行为”的关系 4.一个接口解释了一个或者方法是如何被使用的,接口可以指一个需要绑定的合约 C.traits...2.继承本身不是面向对象的核心,最核心的概念是重用。继承只是代码重用的一种方式,另一种就是组合。 E.命名空间 1.命名空间通过使我们按照组来管理我们的代码以解决冲突的问题。

    75520

    【笔记】《C++Primer》—— 第三部分:设计者的工具

    如果表达式不是引用也不是指针,则其动态类型永远与静态类型一致 派生可以往基类型转换,而基不能隐式反向转换 一个派生的函数如果想要覆盖继承来的虚函数,那必须名称和形参都一致,否则编译器会认为这两个函数是独立的...定义方法是在声明函数名的时候函数体类似显式默认构造的写法改写为=0,只能对虚函数使用这个写法 友元只对被声明的有效,友元的基或派生不是友元 某个对其继承来的成员的访问权限受到两个因素的影响:...,我们可以用尾置返回来完成这个目标: 标准库头文件type_traits中的来进行特殊的类型转换能够动态将这些语言特性消去从传入的参数中提取出我们想要的类型 编译器是从模板函数的调用中推断具体的实参类型的要求在...,那些可变的参数部分称为参数包,由省略号...标记 可变参数的模板函数通常是一种递归函数,一般我们编写的时候都会递归分析包中的内容并调用直到终止,将包中的内容分解成元素称为包扩展 包扩展的一种用法是用来扩展提取输入的参数...即使我们需要特例化所有的类型参数也要保留一个空的尖括号做标记 完全的模板特例化的本质是模板的一个实例,而不是重载,因此特例化不会影响函数的匹配。

    1.7K10

    C++11 变参模板

    2.1.2逗号表达式展开参数包 2.2变参模版 2.2.1偏特化与递归方式展开 2.2.2继承方式展开 3.变参模板的应用 3.1消除重复代码 3.2实现泛化的delegate 4.总结 参考文献...这种展开参数包的方式,不需要通过递归终止函数,是直接在expand函数体中展开的, printarg不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。...,变参模板的参数包展开需要通过模板特化和继承方式去展开,展开方式比变参函数模板要复杂。...下面看一下展开变参模板中的参数包的方法。 2.2.1偏特化与递归方式展开 变参模板的展开一般需要定义两到三个,包括声明和偏特化的模板。...MakeIndexes继承于自身的一个特化的模板,这个特化的模板类同时也在展开参数包,这个展开过程是通过继承发起的,直到遇到特化的终止条件展开过程才结束。

    3.3K51

    c++11增加的变参数模板,今天总算整明白了

    ,但到底是怎么个递归继承法呢?...,所以现在是3个形参,3层继承,顶层基是泛化模板,然后进行了三层派生,这个递归继承的过程是编译器根据代码自行展开的。...再看看对于成员函数print的调用,我的原意是想针对每一种容器类型,都打印出结果,但现在只打印了一种,我们可以想想,对于继承,非虚函数但函数类型相同的情况下,派生的成员函数会覆盖基的成员函数,所以这里结果是正常的...比如上面的age ...和Fargs...都属于包展开,但是要知道,这种形式我们是没有办法直接使用的,那么具体该怎么使用呢,有两种办法: 一是使用递归的办法把形参包里面的参数一个一个的拿出来进行处理,最后以一个默认的函数或者特化模板来结束递归...,传入了多个不同的构造入参,那么这些构造入参是怎么传入到CMan本身的呢,我们看看函数emplace_front的源码实现,如下: #if __cplusplus >= 201103L template

    2.2K20

    EasyC++84,私有继承(二)

    由于Student继承了valarray,而非包含一个valarray的实例,那么我们如何在Average方法的实现当中调用valarray的公有方法呢? 答案是通过解析运算符和名调用。...现在我们知道了使用解析运算符可以访问基的方法,但问题又来了,如果我们要访问的不再是基的方法而是基对象本身,那么我们应该怎么办呢?...由于Student只是继承了string并没有自己的string实例,因此我们需要返回基对象本身。 同样,我们怎么操作呢? 答案是使用强制转换。...引用不会自动发生转换,是因为在私有继承当中,在不进行显式类型转换的情况下,不能将派生的引用或指针赋给基的引用或指针。 那么问题来了,如果我们使用的是公有继承,那么是不是就可以了呢?...原因也简单,首先在不使用类型转换的情况下,os << stu和自身的友元函数类型匹配, 将会发生递归。其次由于C++支持多继承,所以编译器将会无法确定转换成哪个基的类型。

    38310
    领券