CRTP 中间类也需要成为 final

Posted

技术标签:

【中文标题】CRTP 中间类也需要成为 final【英文标题】:CRTP intermediate class that needs to also be made final 【发布时间】:2012-04-17 13:07:04 【问题描述】:

我有一个 CRTP 类的继承链。 CRTP 类相互派生,直到“最终”派生类将自身作为 CRTP 参数传递并最终确定继承链。

template <class W>
struct Base

    .....
;
template <class W>
struct Derived_inheritable: public Base<W>

....


template <class W>
struct Derived2_inheritable: public Derived_inheritable<W>

....


...

我想要做的是能够在 CRTP 继承链的每一层都有这样的“最终”最终用户类,不涉及模板:

typedef Derived1_inheritable<Derived1> Derived1;

你可以猜到,这个 typedef 不起作用,因为它引用了它自己定义的类型。问题是如何实现这一目标? 我能想到的方法是:

struct Derived1: public Derived1_inheritable<Derived1>

   //not convenient, need to redefine at least a forwarding constructor

正如代码中的注释所说,这不是一个非常优雅的解决方案 - 我需要重新定义构造函数以转发到基本构造函数。有人知道更优雅的方式吗?

【问题讨论】:

我不能说你的例子很有启发性,而且问题的措辞是 finalintermediate 类,是自相矛盾的.你到底想达到什么目的? 这里的中间意味着我有相互派生的CRTP类,直到最终派生类将自己作为CRTP参数传递并最终确定继承链。我想要做的是能够在 CRTP 继承链的每个级别都有这样的“最终”类 【参考方案1】:

typedef Derived1_inheritable Derived1;

那行没有意义,模板的参数是一个 type 但你试图传递一个 template (顺便说一下你正在实例化的同一个模板,但是除了这个额外的怪癖之外,事实是您的模板采用 type 作为参数,而您传递的是非类型)

从问题中并不清楚您要达到什么目标。你应该努力陈述你的目标,而不是你实现该目标的方法

我想为每个非模板的 DerivedX_inheritable 创建一个“最终”类,并将自身作为 W 参数传递。

这正是在您提供的代码中完成的:

struct Derived1: public Derived1_inheritable<Derived1> 

这是一个类型定义(创建一个“最终”类)。事实上,您的 CRTP 基础需要最终用户必须提供的参数以及转发构造函数的需要,这只是您设计的副作用。

【讨论】:

好吧,我认为最好的说明方法是编写显示类层次结构的代码。我猜 typedef 行是这里令人困惑的地方,所以我在第一个答案的评论中澄清了它。 是的,这是一个副作用,我正在寻找一种方法来弥补它,通过在每个级别定义不涉及模板的最终用户类。我正在寻找我找到的解决方案的替代解决方案,因为我不想创建(因此 typedef,如果可能的话)其他类(和构造函数) @AlexanderVassilev:不管你喜不喜欢,这就是你的设计所带来的。你在那里无能为力。您可以尝试编写一个宏来获取一些样板文件,但是您需要定义一个新类型,并且该类型必须有一个构造函数 我得出了同样的结论。没有其他方法可以实现这种设计的好处,因此与好处相比,这种不便之处非常小。感谢您的帮助。【参考方案2】:

我想我找到了一个优雅的解决方案:

template <class W>
struct Base

   .....
;
template <class W>
struct Derived_inheritable: public Base<W>

....


//solution
struct Derived2_dummy;

template <class W=derived2d_ummy>
struct Derived2_inheritable: public Derived_inheritable<W>

....

struct derived2_dummy: public: Derived_inheritable<>;
typedef Derived2_inheritable<> Derived2;

【讨论】:

以上是关于CRTP 中间类也需要成为 final的主要内容,如果未能解决你的问题,请参考以下文章

为什么Java匿名内部类访问的外部局部变量或参数需要被final修饰

在Java中String类为什么要设计成final?String真的不可变吗?其他基本类型的包装类也是不可变的吗?

很快,有没有办法让 UIView 类也成为 MPMediaPickerControllerDelegate?

什么是奇怪的重复模板模式(CRTP)?

基于 CRTP 的解决方案会是啥样子?

浅谈 CRTP:奇异递归模板模式