C++23 为我们提供了一种编写 mixin 类的新方法(而不是 CRTP)。是否存在任何情况下 CRTP 仍会受到青睐?
CRTP 是 C++ 中的一个强大的惯用法,它利用模板在运行时自动生成特定于类型的行为。这通常用于创建 mixin 类。
C++23 引入了显式对象参数,它允许在非静态成员函数的参数列表中显式引用类名。因此,模板非静态成员函数可以访问派生类,从而无需在派生类上专门使用 mixin。
这是一个说明新旧方法的示例。
// classic CRTP (old approach)
template <typename T>
class MyMixin<T> {
// ...
void foo() {
// Stuff using T...
}
};
// have to specialize MyMixin over MyType
class MyType : public MyMixin<MyType> {
// ...
};
// explicit object parameter (C++23 approach)
class MyMixin {
// ...
template <typename T>
void foo(this T* self) {
// Stuff using T...
}
};
// better syntax for mixins
class MyType : public MyMixin {
// ...
};
显然,新方法使派生类中的语法更加清晰。例如,它可以让我们避免像这样的棘手事情:
template<typename x, typename y, typename z, typename w>
class MyWackyContainer : public MyMixin<MyWackyContainer<x,y,z,w>>
因为我们不必使用新方法向
MyMixin
提供模板参数。
根据本文的摘要(解决了前面提到的问题),
虽然[添加显式对象参数]已经消除了在许多地方使用 CRTP 的需要,但仍然存在必须使用此模式来表达的情况。
我能想到的 CRTP 和新方法之间唯一的功能区别是 CRTP 让我们在声明非函数成员和静态成员函数时引用类型。 但是有什么情况下这实际上有用吗?
(第二个问题:我的理解正确吗?我错过了什么吗?)
来自 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html#propose-syntax
具有显式对象参数的成员函数不能是静态或虚拟的,并且它们不能具有 cv 或 ref 限定符。我们将在后续章节中讨论对静态和虚拟的限制。
所以CRTP仍然是
virtual
和static
功能的唯一途径。