Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are template mixins in C++ not more of a mainstay?

I use template mixins in C++ a lot, but I'm wondering why the technique isn't used more. It seems like the ultimate in reuse. This mix of power and efficiency is one of the reasons I really love C++ and can't see myself moving to a JIT language.

This article: http://www.thinkbottomup.com.au/site/blog/C%20%20_Mixins_-_Reuse_through_inheritance_is_good is a good backgrounder if you don't know what they are, and puts the case so clearly in terms of reuse and performance.

like image 519
Jesse Pepper Avatar asked Jan 06 '12 08:01

Jesse Pepper


2 Answers

Templates require implementation to be visible in the translation unit, not just at link time (C++11 addresses that if you'll only use a pointer or reference to instantiations). This is a major issue for low-level code in enterprise environments: changes to the implementation will trigger (might or might not be automatically) massive numbers of libraries and clients to recompile, rather than just need relinking.

Also, each template instantiation creates a distinct type, which means functions intended to work on any of the template instantions have to be able to accept them - either themselves being forced to be templated, or they need a form of handover to runtime polymorphism (which is often easy enough to do: just need an abstract base class expressing the set of supported operations, and some "get me a accessor" function that returns a derived object with a pointer to the template instantiation and related entires in the virtual dispatch table).

Anyway, these issues are typically manageable, but the techniques to manage the coupling, dependencies and interfaces involved are a lot less publicised, understood and readily available than the simple mixin technique itself. Same is true of templates and policy class BTW.

like image 32
Tony Delroy Avatar answered Nov 08 '22 20:11

Tony Delroy


The problem with mixins is... construction.

class Base1 { public: Base1(Dummy volatile&, int); };

class Base2 { public: Base2(Special const&, Special const&); };

And now, my super mixin:

template <typename T>
struct Mixin: T {};

Do you notice the issue here ? How the hell am I supposed to pass the arguments to the constructor of the base class ? What kind of constructor should Mixin propose ?

It's a hard problem, and it has not been solved until C++11 which enhanced the language to get perfect forwarding.

// std::foward is in <utility>

template <typename T>
struct Mixin: T {
  template <typename... Args>
  explicit Mixin(Args&&... args): T(std::forward<Args>(args...)) {}
};

Note: double checks are welcome

So now we can really use mixins... and just have to change people habits :)

Of course, whether we actually want to is a totally different subject.

One of the issues with mixins (that the poor article you reference happily skip over) is the dependency isolation you completely lose... and the fact that users of LoggingTask are then bound to write template methods. In very large code bases, more attention is given to dependencies than to performance, because dependencies burn human cycles while performance only burn CPU cycles... and those are usually cheaper.

like image 82
Matthieu M. Avatar answered Nov 08 '22 20:11

Matthieu M.