c++crtp

Why is CRTP not working in the following function?


I am learning CRTP C++ pattern

My code

template<class Type>
class BaseOrder {
public:
    void sendOrder() {static_cast<Type*>(this)->send();}
    void send() { cout << "Send Base" << endl;}
};

class DerivedOrder1 : public BaseOrder<DerivedOrder1> {
public:
    void send() { cout << "Send DerivedOrder1" << endl;}
};

class DerivedOrder2 : public BaseOrder<DerivedOrder2> {
public:
    void send() { cout << "Send DerivedOrder2" << endl;}
};

template<class T>
void handleOrder(BaseOrder<T> order) {
    order.send();
}

int main() {
    BaseOrder<DerivedOrder1> obj1;
    handleOrder(obj1); // Send Base

    BaseOrder<DerivedOrder2> obj2;
    handleOrder(obj2); // Send Base
}

I see output:

Send Base
Send Base

But I expect

Send DerivedOrder1
Send DerivedOrder2

How to fix my code? Did I miss something?


Solution

  • There are several mistakes in your code:

    send is not virtual, you probably want to call sendOrder instead. and you should pass that argument by reference to avoid slicing which would make the call to sendOrder UB as the cast would be invalid:

    template <class T>
    void handleOrder(BaseOrder<T>& order) {
        order.sendOrder();
    }
    

    in main, you don't create the derived class, it should be

    DerivedOrder1 obj1;
    handleOrder(obj1); // Send Base
    
    DerivedOrder2 obj2;
    handleOrder(obj2); // Send Base
    

    Demo

    An improvement to avoid those mistakes would be to make some methods protected:

    template<class Type>
    class BaseOrder {
    protected:
        BaseOrder() = default;
        BaseOrder(const BaseOrder&) = default;
        BaseOrder& operator=(const BaseOrder&) = default;
    public:
    // ..
    };
    

    Demo