2

In my widget library I'd like to implement some kind of call chain to initialize a user supplied VIEW class which might(!) be derived from another class which adds some additional functionality like this:

#include <iostream>

template<typename VIEW>
struct App
{
    VIEW view;
    void init() {view.initialize(); }
};

template<typename DERIVED>
struct SpecializedView
{
    void initialize()
    {
        std::cout << "SpecializedView" << std::endl;
        static_cast<DERIVED*>(this)->initialize();
    }
};

struct UserView : SpecializedView<UserView>
{
    void initialize() {std::cout << "UserView" << std::endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    // Cannot be altered to: App<SpecializedView<UserView> > app;
    App<UserView> app; 
    app.init();
    return 0;
}

Is it possible to achieve some kind of call chain (if the user supplied VIEW class is derived from "SpecializedView") such that the output will be:

console output:

SpecializedView
UserView

Of course it would be easy to instantiate variable app with the type derived from but this code is hidden in the library and should not be alterable. In other words: The library code should only get the user derived type as parameter.

fhw72
  • 798
  • 1
  • 8
  • 19
  • 2
    Explicit public initialization methods are very bad. – Puppy Dec 18 '12 at 10:56
  • 1
    @DeadMG: The example code above was stripped down to a minimum obviously! I didn't want to add more code than necessary to describe my intention. – fhw72 Dec 18 '12 at 11:05

1 Answers1

1

You could write another function that calls initialize() on the class and on the base class if it exists and defines an initialize() method, too:

template <class T>
void callInitialize(T* t) {
    t->initialize();
    IF_EXISTS(base_class<T>::bc::initialize)
        callInitialize<base_class<T>::bc>(t);
}

Of course, the order of the calls can be reversed.

See Is it possible to write a template to check for a function's existence? on the implementation of IF_EXISTS. Also, base_class<T> is not a standard construct, and this answer suggests that this cannot be done automatically. The semantics would look like this:

template<T>
struct base_class<T> {
    typedef void bc;
};

template<>
struct base_class<UserView> {
    typedef SpecializedView<UserView> bc;
};

Perhaps your framework permits a semi-automatic way to do this.

Community
  • 1
  • 1
krlmlr
  • 22,030
  • 13
  • 107
  • 191