Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does c++ guarantee down-casting grandmother base class to grand child class like curiously recurring template pattern?

Tags:

c++

downcast

I would like to know whether c++ guarantees down-casting grandmother base class to grand child class like curiously recurring template pattern. The following code works well in my environment. However I am not sure it works any conditions/environments. Please tell me what you know. Thank you very much.

PS. Honestly said, I am not sure my way of asking stack overflow is ok or bad. If you find the bad points, please let me know. Thank you again.

#include <iostream>

template <typename GrandChild>
class GrandBase {
public:
    void print(void) {
        const GrandChild* grand_child = static_cast<const GrandChild*>(this);
        std::cout << "GrandChild::value = " << grand_child->grand_child_value << std::endl;
    }
};

template <typename Derived>
class BridgeClass : public GrandBase<Derived> {};

class GrandChild : public BridgeClass<GrandChild> {
public:
    GrandChild() = default;
    virtual ~GrandChild() = default;

    int grand_child_value = 17;
};

void test_down_casting_to_grand_base(void) {
    GrandChild a;
    a.print();
}

int main(int argc, char **argv) {
    test_down_casting_to_grand_base();
    return 0;
}

The output is

GrandChild::value = 17
like image 650
mora Avatar asked Jan 03 '16 04:01

mora


1 Answers

Given the code you've presented, yes, the standard requires that this be permitted. As long as you use the CRTP correctly, the standard requires that it works. Even with other classes in-between.

Do note however that the base class can also access any public members of the middle class. The top-most class overrides it if names conflict, of course.

Also, note that there's a conceptual difference between passing the most derived class and passing the first derived class. The base class can only (directly) access the class you passed in. So if you only pass in the first derived class, if that one itself uses the CRTP with its derived class, your base class won't know about it. Whereas if you pass the most derived class, it can access the most derived one and any public interfaces inbetween.

Which you want to use depends on what effect you intend.

like image 56
Nicol Bolas Avatar answered Sep 19 '22 10:09

Nicol Bolas