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

2

9

Short Version of Question

C++23 gives us a new way to write mixin classes (instead of CRTP). Is there any context where CRTP would still be preferred?

Summary of the Two Approaches

CRTP is a powerful idiom in C++ that leverages templates to automatically generate type-specific behavior at runtime. This is often used to create mixin classes.

C++23 introduces explicit object parameters, which allow the class name to be referenced explicitly in the parameter lists of non-static member functions. As a result, template non-static member functions can access the derived class, eliminating the need to specialize the mixin over the derived class.

Here is an example illustrating the old and new approach.

// 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 {
    // ...
};

Clearly, the new approach leads to cleaner syntax in the derived class. For instance, it lets us avoid gnarly things like this:

template<typename x, typename y, typename z, typename w>
class MyWackyContainer : public MyMixin<MyWackyContainer<x,y,z,w>>

since we don't have to provide a template parameter to MyMixin with the new approach.

Full Question

Per the abstract of this paper (which addresses the previously mentioned problem),

While [adding explicit object parameters] has removed the need for using CRTP in many places, there still exist cases that must be expressed using this pattern.

The only functional difference I could think of between CRTP and the new approach, is that CRTP would let us reference the type when declaring non-function members and static member functions. But is there any situation where this is actually useful?

(Secondary question: Is my understanding correct? Did I miss anything?)

Sandstone answered 26/10, 2023 at 23:33 Comment(5)
Why don't you need it for non-static member variables?Hypothetical
When you say "explicit object parameters", I believe you mean deducing this?Rata
@DrewDormann Yes, that's a colloquial name for it. The name in the standard is explicit object parameter.Sandstone
@user253751 I'm asking why we need it! I can't think of any examples. Hence the question :)Sandstone
Deducing this only helps inside functions... classes also contain e.g. non-static member variables with value assignment expressions, type aliases etc. where you may want to use values/types/functions via old-school CRTP.Treaty
M
5

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

Member functions with an explicit object parameter cannot be static or virtual and they cannot have cv- or ref-qualifiers.

So CRTP is still the only way for virtual and static functions.

Metabolite answered 27/10, 2023 at 2:41 Comment(0)
K
1

The big difference is that the CRTP base classes are distinct types, for which there is no equivalent type in the explicit object parameter version. Those types can be useful.

The static member thing is one example. The fact that you have distinct types allows you to implement static members that are only shared within a single derived class and not between all of them.

But also you may just need those types for whatever, as a place to put type alias definitions for example.

Kharkov answered 27/10, 2023 at 16:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.