“奇怪的重复模板模式”的实际用途
What are some practical uses for the "Curiously Recurring Template Pattern"? The "counted class" example commonly shown just isn't a convincing example to me.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
模拟动态绑定。
避免虚拟函数调用的成本,同时保留一些层次结构的好处,对于子系统来说是一个巨大的胜利,可以在我当前正在从事的项目中实现这一点。
Simulated dynamic binding.
Avoiding the cost of virtual function calls while retaining some of the hierarchical benefits is an enormous win for the subsystems where it can be done in the project I am currently working on.
它对于 mixins (我的意思是您继承以提供功能的类)也特别有用,它们本身需要知道它们正在操作的类型(因此需要是模板)。
在Effective C++中,Scott Meyers 提供了一个类模板 NewHandlerSupport作为示例。 它包含一个静态方法来覆盖特定类的新处理程序(与 std::set_new_handler 对默认运算符 new 的作用相同),以及一个使用该处理程序的运算符 new。 为了提供每个类型的处理程序,父类需要知道它正在作用于什么类型,因此它需要是一个类模板。 模板参数是子类。
如果没有 CRTP,您实际上无法做到这一点,因为您需要单独实例化 NewHandlerSupport 模板,并使用单独的静态数据成员来存储每个使用它的类的当前 new_handler。
显然,整个示例是极其非线程安全的,但它说明了这一点。
Meyers 认为 CRTP 可以被认为是“Do It For Me”。 我想说任何 mixin 通常都是这种情况,并且 CRTP 适用于您需要 mixin 模板而不仅仅是 mixin 类的情况。
It's also especially useful for mixins (by which I mean classes you inherit from to provide functionality) which themselves need to know what type they are operating on (and hence need to be templates).
In Effective C++, Scott Meyers provides as an example a class template NewHandlerSupport<T>. This contains a static method to override the new handler for a particular class (in the same way that std::set_new_handler does for the default operator new), and an operator new which uses the handler. In order to provide a per-type handler, the parent class needs to know what type it is acting on, so it needs to be a class template. The template parameter is the child class.
You couldn't really do this without CRTP, since you need the NewHandlerSupport template to be instantiated separately, with a separate static data member to store the current new_handler, per class that uses it.
Obviously the whole example is extremely non-thread-safe, but it illustrates the point.
Meyers suggests that CRTP might be thought of as "Do It For Me". I'd say this is generally the case for any mixin, and CRTP applies in the case where you need a mixin template rather than just a mixin class.
如果您认为仅在方法扩展时需要传递给超类的子类类型,那么 CRTP 就会变得不那么好奇。
那么所有类型都被定义了。
您只需要将符号子类类型导入到超类中的模式,但这只是一个前向声明 - 因为所有正式模板参数类型都是根据定义的 - 就超类而言。
我们以稍微修改的形式使用,将特征类型结构中的子类传递给超类,以使超类可以返回派生类型的对象。 该应用程序是一个几何演算(点、向量、线、框)库,其中所有通用功能都在超类中实现,子类仅定义特定类型:CFltPoint 继承自 TGenPoint。 而且 CFltPoint 在 TGenPoint 之前就存在,因此子类化是重构它的自然方式。
The CRTP gets a lot less curious if you consider that the subclass type that is passed to the superclass is only needed at time of method expansion.
So then all types are defined.
You just need the pattern to import the symbolic subclass type into the superclass, but it is just a forward declaration - as all formal template param types are by definition - as far as the superclass is concerned.
We use in a somewhat modified form, passing the subclass in a traits type structure to the superclass to make it possible for the superclass to return objects of the derived type. The application is a library for geometric calculus ( points, vectors, lines, boxes ) where all the generic functionality is implemented in the superclass, and the subclass just defines a specific type : CFltPoint inherits from TGenPoint. Also CFltPoint existed before TGenPoint, so subclassing was a natural way of refactoring this.
通常,它用于类似多态的模式,您不需要在运行时仅在编译时选择派生类。 这样可以节省运行时虚函数调用的开销。
Generally it is used for polymorphic-like patterns where you do not need to be able to choose the derived class at runtime, only at compile time. This can save the overhead of the virtual function call at runtime.
对于 CRTP 的实际库使用,请查看 ATL 和 WTL (wtl.sf.net)。 它被广泛用于编译时多态性。
For a real-world library use of CRTP, look at ATL and WTL (wtl.sf.net). It is used extensively there for compile-time polymorphism.