何时在 c++23 中对显式对象参数使用 CRTP?

When to use CRTP over explicit object parameter in c++23?

提问人:jepugs 提问时间:10/27/2023 更新时间:10/28/2023 访问量:168

问:

问题的简短版本

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 允许我们在声明非函数成员和静态成员函数时引用该类型。但是,有没有一种情况是这实际上是有用的呢?

(次要问题:我的理解正确吗?我错过了什么吗?

C++ 模板 CRTP C++23

评论

1赞 user253751 10/27/2023
为什么非静态成员变量不需要它?
0赞 Drew Dormann 10/27/2023
当你说“显式对象参数”时,我相信你的意思是推导这个
0赞 jepugs 10/27/2023
@DrewDormann 是的,这是它的俗称。标准中的名称是显式对象参数
0赞 jepugs 10/27/2023
@user253751我在问我们为什么需要它!我想不出任何例子。因此,问题:)
2赞 Tony Delroy 10/27/2023
推断这一点只会对内部函数有所帮助......例如,类还包含具有值赋值表达式、类型别名等的非静态成员变量,您可能希望通过老式 CRTP 使用值/类型/函数。

答:

4赞 Jarod42 10/27/2023 #1

低至 https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html#proposed-syntax

具有显式对象参数的成员函数不能是静态的或虚拟的,并且不能具有 cv 或 ref 限定符。

因此,CRTP仍然是唯一的方式和功能。virtualstatic

1赞 jwezorek 10/28/2023 #2

最大的区别在于 CRTP 基类是不同的类型,在显式对象参数版本中没有等效的类型。这些类型可能很有用。

静态成员就是一个例子。由于具有不同的类型,因此可以实现仅在单个派生类中共享的静态成员,而不是在所有派生类之间共享的静态成员。

但是,您可能只需要这些类型来做任何事情,例如,作为放置类型别名定义的地方。