Inheriting a list of template classes when a list of template arguments is provided

I am trying to write metaprogramming code to:

  • Inheritance from some class foo<c1, c2, c3, ...> leads to inheritance from key<c1>, key<c2>, key<c3>, ...
  • The simplest approach does not work this way because you cannot inherit the same empty class more than once.
  • The processing of the "..." section is not very beautiful (since it is a pasta copy), but it works.

So here is an attempt:

 template<char c0, typename THEN, typename ELSE> struct char_if { typename THEN type; }; template<typename THEN, typename ELSE> struct char_if<0, THEN, ELSE> { typename ELSE type; }; class emptyClass {}; template<char c> class key { char getKey(){return c;} }; template<char c0, char c1, char c2, char c3, char c4> class inheritFromAll { typename char_if<c0, key<c0>, emptyClass>::type valid; class inherit : valid , inheritFromAll<c1, c2, c3, c4, 0>::inherit {}; }; template<char c1, char c2, char c3, char c4> class inheritFromAll<0, c1, c2, c3, c4> { class inherit {}; }; template<char c0 = 0, char c1 = 0, char c2 = 0, char c3 = 0, char c4 = 0> class whatINeedToDo : public inheritFromAll<c0, c1, c2, c3, c4>::inherit { bool success(){return true;} }; int main() { whatINeedToDo<'A', 'B', 'c', 'D'> experiment; return 0; } 

I initially, although I could use Boost :: Mpl to do this, but I honestly could not figure out how; I could not understand how you go around list<...> without explicitly specifying the part ...

Simply:

 template<> class key<0> {}; 

doesn't work, because if I have more than one parameter 0 , I try to inherit the same thing twice. (If you can come up with a workaround for this, this will also work).

I have not tried macros either, because I think I know less of them than I know metaprogramming, so they can work as a solution.

Any ideas?

Edit: I have a bad decision. I still need metaprogramming for training, but the bad solution is this:

 template<char c1, char c2, char c3> class inheritFromMany : public key<c1> , public key<c2> , public key<c3> { }; template<char c1, char c2> class inheritFromMany<c1, c2, 0> : key<c1> , key<c2> { }; 

Edit2: Woof, but I forgot the part. I need to pass the variable to the constructor "key" - this is the same in all cases, but it is necessary.

Edit3: addressing comments:

  • I do not expect the user to present the same character more than once. If they did, I would only want to inherit this key once - I mean, I think I did not mention this because you cannot do this? Why don't other simpler solutions work?
  • The actual point of this is that the key is a wrapper for the behavior of the signal / slot (channel). The channel stores a callback list, which is actually just a virtual key<ch>::callback . Thus, key inheritance gives you access to this key channel, allows (or does) you provide a callback. keyInput<ch1, ch2, ch3,...> is a wrapper for this, so you do not need key<ch1>, key<ch2>, key<ch3>
+4
source share
1 answer

Not to mention what you really want to achieve, this is basically an academic exercise ... but here is one way to use MPL for linear inheritance:

 template<class T> struct key { enum { value = T::value }; char getKey() { return value; } }; template<class Values> struct derivator : mpl::inherit_linearly< Values , mpl::inherit< mpl::_1, key<mpl::_2> > >::type {}; // usage: typedef mpl::vector_c<char, 1,2,3> values; typedef derivator<values> generated; // or: derivator< mpl::vector_c<char, 1,2,3> > derived; 

Perhaps you can clarify on this basis what you need.

I need to pass the variable to the constructor `` key '' - this is the same in all cases, but it is necessary.

Do you want you to pass the parameter through the inheritance chain to all the constructors? Then consider solutions to this .


As for the mpl::vector_c in the visible interface, you can use your previous approach and embed it inside only by inserting non-zero values ​​into it:

 template<char c, class S> struct push_char { typedef typename mpl::push_front<S, mpl::char_<c> >::type type; }; template<class S> struct push_char<0, S> { typedef S type; // don't insert if char is 0 }; template<char c1=0, char c2=0, char c3=0> struct char_vector { // build the vector_c typedef typename push_char<c1 , typename push_char<c2 , typename push_char<c3 , mpl::vector_c<char> >::type>::type>::type type; }; template<char c1=0, char c2=0, char c3=0> struct derivator : mpl::inherit_linearly< typename char_vector<c1,c2,c3>::type , mpl::inherit< mpl::_1, key<mpl::_2> > >::type {}; 
+3
source

Source: https://habr.com/ru/post/1302425/


All Articles