c++ - Is this use pattern of virtual inheritance for "method injection" a known paradigm? -
c++ - Is this use pattern of virtual inheritance for "method injection" a known paradigm? -
yesterday, came across question: forcing unqualified names dependent values originally, seemed specific question related broken vc++ behaviour, while trying solve it, stumbled upon utilize pattern of virtual inheritance hadn't come across before (i explain in second, after telling question have). found interesting, looked on , google, couldn't find anything. maybe, don't know right name ("method injection" 1 of guesses) , known. part of question community: is mutual utilize pattern or special case of known paradigm? see problems/pitfalls can avoided different solution?
the problem pattern can solve following: suppose have class morph
method dowork()
. within dowork()
, several functions called implementation supposed selectable user (that's why class called morph
). let's phone call called functions chameleons (since morph class doesn't know in end). 1 way accomplish of course of study create chameleons virtual methods of morph class, user can derive morph
, override selected methods. if user expected utilize different combinations selecting implementation different chameleons. then, every combination, new class has defined. in addition, if there multiple morph
-like classes same functions supposed chameleons? how can user reuse replacements implemented?
as "multiple classes have defined" problem, immediately, templates jump one's mind. can't user select chameleon implementations wants passing classes template parameters define desired implementation? i.e. morph<replaceab>
should replace chameleons a()
, b()
in dowork()
implementation, leaving possible other chameleons, e.g., c()
, untouched. c++11 , variadic templates, combinations not problem: morph<replaceab, replacec, whatevermore...>
well, that's exactly, pattern can (see below explanation):
#include <iostream> using namespace std; // list chameleons, create of them // pure virtual, custom implementation *required*. struct chameleons { virtual void a() { cout << "default a" << endl; } virtual void b() { cout << "default b" << endl; } virtual void c() { cout << "default c" << endl; } }; // chameleon implementations , b struct replaceab : virtual chameleons { virtual void a() { cout << "alternative a" << endl; } virtual void b() { cout << "alternative b" << endl; } }; // chameleon implementation c struct replacec : virtual chameleons { virtual void c() { cout << "alternative c" << endl; } }; // a(), b(), c() in class made chameleons // inheriting virtually chameleons template <typename... replace> struct morph : virtual chameleons, replace... { void dowork() { a(); b(); c(); cout << endl; } }; int main() { //default implementations morph<>().dowork(); //replace , b morph<replaceab>().dowork(); //replace c morph<replacec>().dowork(); //replace a, b , c; morph<replaceab,replacec>().dowork(); }
the output of following:
default default b default c alternative alternative b default c default default b alternative c alternative alternative b alternative c
seeing working solution only, problem above thought not obvious: couldn't morph
derive classes specified template parameters, chameleons a()
, b()
, c()
taken whatever morph
inherits from? not possible, because calls chameleons not depend on template parameters, , such non-dependent names not looked in dependent inherited classes (try it, if want). means, somehow have accomplish chameleon calls bind can later replaced desired implementation.
that's virtual inheritance comes in: letting morph
inherit chameleons
(non-dependent on template parameters), unqualified chameleon calls in dowork()
bind virtual functions in chameleons
. because morph
, replacement
classes inherit virtually chameleons
, there single chameleons
object in morph
object, , virtual function calls dispatched at run-time implementation in derived class, "smuggle in" through templated inheritance. so, although unqualified chameleon names in dowork()
cannot resolved desired implementation @ compile time (in accordance standard), can still called layer of indirection through virtual base of operations class. funny, huh? (unless tell me much easier in different way or pattern known.)
your solution works fine. virtual inheritance avoids ambiguity errors. variadic template brings elegant instantiation syntax. instead of like:
class m1 : public replaceab, replacec {} i1; i1.dowork();
you have 1 line:
morph<replaceab, replacec>().dowork();
from point of view proposed pattern not common. same time, new? well, there millions , millions lines of code... chance used similar not 0 @ all. never know sure.
c++ inheritance virtual-inheritance
Comments
Post a Comment