mardi 17 mars 2015

c++ library: application inserts a class in inheritance hierarchy


I have a library with the following inheritance hierarchy (a mock-up):



struct Xbase {
virtual void f() = 0;
};

struct Derived1 : public Xbase {
void f() { std::cerr << "Derived1::f\n"; }
};

struct Derived2 : public Xbase {
void f() { std::cerr << "Derived2::f\n"; }
};
struct Storage {
std::map<int, Xbase*> data;
Xbase* get(int i) {
auto it = data.find(i);
return (it == data.end() ) ? nullptr : it->second;
}
};


The library keeps track of pointers to base struct, and allows to retrieve them, in this small example by an integer id. There is an application that uses the library, and wants to provide some functionality by introducing a second base class Ybase:



struct Ybase {
virtual void g() { std::cerr << "Ybase::g\n"; }
};

struct AppDerived1 : public Derived1, public Ybase {
void f() { std::cerr << "AppDerived1::f\n"; }
};

struct AppDerived2 : public Derived2, public Ybase {
void f() { std::cerr << "AppDerived2::f\n"; }
};


Of course things like



int i = 5;
Storage storage;
Xbase* xbase = storage.get(i);
Ybase* ybase = static_cast<Ybase *>(xbase);


do not work very well



$ g++ -std=c++11 t.cpp
t.cpp: In function ‘int main()’:
t.cpp:21:45: error: invalid static_cast from type ‘Xbase*’ to type ‘Ybase*’


I thought of providing a template version of derived classes so that the app developer could insert his class into the library hierarchy.


Library:



template<typename T>
struct Derived1 : public T {
void f() { std::cerr << "Derived1::f\n"; }
};


App owner:



struct Ybase : public Xbase {
virtual void g() { std::cerr << "Ybase::g\n"; }
};

struct AppDerived1 : public Derived1<Ybase> {
...
};
/* same for AppDerived2 */
Xbase* xbase = storage.get(i);
Ybase* ybase = static_cast<Ybase *>(xbase);
ybase->g();


This creates a single inheritance line, and the cast should work.


I'd like to understand if this is a good or a bad idea, and what could be the alternative. Please note that I do need the common base class Xbase in the hierarchy because I have to be able to retrieve a base class pointer from external data like names and ids. The problem for the app developer is that the app also needs its base pointer since the app does not know the type of the object (AppDerived1 or 2) it receives. Thanks for reading.




Aucun commentaire:

Enregistrer un commentaire