c++ decorator pattern, static polymorphism with templates and registering callback methods

前端 未结 1 1847
北荒
北荒 2021-01-25 22:22

I am attempting to use static polymorphism to create a decorator pattern. As to why I do not use dynamic polymorphism, please see this QA. Basically, I could not dynamic_c

相关标签:
1条回答
  • 2021-01-25 23:11

    You started using mixins, so use them to the end.
    It follows a minimal, working example:

    #include<iostream>
    
    struct I {
        virtual void et() = 0;
    };
    
    template<typename... T>
    struct S: I, private T... {
        S(): T{}... {}
    
        void et() override {
            int arr[] = { (T::et(), 0)..., 0 };
            (void)arr;
            std::cout << "S" << std::endl;
        }
    };
    
    struct A {
        void et() {
            std::cout << "A" << std::endl;
        }
    };
    
    struct B {
        void et() {
            std::cout << "B" << std::endl;
        }
    };
    
    int main() {
        I *ptr = new S<A,B>{};
        ptr->et();
        delete ptr;
    }
    

    As in the original code, there is an interface I that offers the virtual methods to be called.
    S implements that interface and erases a bunch of types passed as a parameter pack.
    Whenever you invoke et on a specialization of S, it invokes the same method on each type used to specialize it.

    I guess the example is quite clear and can serve as a good base for the final code.
    If I've understood correctly the real problem, this could be a suitable design for your classes.

    EDIT

    I'm trying to reply to some comments to this answer that ask for more details.

    A specialization of S is all the (sub)objects with which it is built.
    In the example above, S<A, B> is both an A and a B.
    This means that S can extend one or more classes to provide common data and can be used as in the following example to push around those data and the other subobjects:

    #include<iostream>
    
    struct I {
        virtual void et() = 0;
    };
    
    struct Data {
        int foo;
        double bar;
    };
    
    template<typename... T>
    struct S: I, Data, private T... {
        S(): Data{}, T{}... {}
    
        void et() override {
            int arr[] = { (T::et(*this), 0)..., 0 };
            (void)arr;
            std::cout << "S" << std::endl;
        }
    };
    
    struct A {
        void et(Data &) {
            std::cout << "A" << std::endl;
        }
    };
    
    struct B {
        void et(A &) {
            std::cout << "B" << std::endl;
        }
    };
    
    int main() {
        I *ptr = new S<A,B>{};
        ptr->et();
        delete ptr;
    }
    
    0 讨论(0)
提交回复
热议问题