Tuesday, October 18, 2016

Easing maintenance of class template parameter lists by deriving from them.

 This seems to me related to "template traits parameters"
 and "the curiously recurring template pattern", but it is a bit different than both.

 So I have just a few explict template instantiations,
 and my code is mostly not in headers, so previously I had:

 template <typename T1, bool f1, bool f2, etc.>
 class foo_t
 {
   void Function1();
   void Function2();
   etc. a fair number
 };


 and then

 template <typename T1, bool f1, bool f2, etc.>
 void class foo_t<T1, f1, f2>::Function1() { ... }

 template <typename T1, bool f1, bool f2, etc.>
 void class foo_t<T1, f1, f2>::Function2() { ... }

 etc. a fair number

 This bugged me for two reasons:

 1. The usual unnamed parameter problem, what does true/false mean:

 foo_t<x, true, false> mean.

 and then in the debugger:
   foo_t<x, 1, 0>

 Functions have the same problem.

 Coworker highlighted this actually.

 2. As there were a fair number of functions, changing the template parameter list was tedious. Because, again, I had a fair number of functions, in a separate .cpp file.

 So, I finally decided to use variadic templates and I now have:

 template <typename ...Types> 
 struct foo_t : Types... { ... }; 


 foo_t inherits from its template parameters.

 Now changing the parameter list is not tedious.

 Instantiations are like:

 foo_t<fooarg1<true>, fooarg2<false>>

 The factoring of the template parameter-dependantness can take multiple forms.

 They include:

 template <bool f> struct fooarg1;

 template <> struct fooarg1<false> { implement stuff here };
 template <> struct fooarg1<true> { implement stuff here };

 template <bool f> struct fooarg2 { enum { arg2 = f }; };


 template <typename ...Types>
 void foo_t<Types...>::function1() { if (arg2) ... }


 This second case might look like a conditional branch, but any half decent
 compiler will optimize it.


 Debugger now says foo_t<x, fooarg1<0>, fooarg2<1>> etc.

 and changing the template parameter list requires only localized edits.
 (Again, I have very few instantiations).


 There were other details as to how this affected my interaction with assembly,
 this it shouldn't matter for typical applications (Yes, I use C++ templates and assembly).


 - Jay