Mechanics of multiple inheritance compared to templates wrt building flexible designs - c++

This is a narrower version of the question put on hold due to being too broad.
On pages 6-7 of Modern C++ Design, Andrei Alexandrescu lists three ways in which the multiple inheritance is weaker than templates with respect to building flexible designs. In particular, he states that the mechanics provided by multiple inheritance is poor (the text in square brackets and formatting are mine as per my understanding of the context):
In such a setting [i.e. multiple inheritance], [to build a flexible SmartPtr,] the user would build a multithreaded, reference-counted smart pointer class by inheriting some BaseSmartPtr class and two classes: MultiThreaded and RefCounted. Any experienced class designer knows
that such a naïve design does not work.
...
Mechanics. There is no boilerplate code to assemble the inherited components in a controlled
manner. The only tool that combines BaseSmartPtr, MultiThreaded, and RefCounted
is a language mechanism called multiple inheritance. The language applies
simple superposition in combining the base classes and establishes a set of simple rules
for accessing their members. This is unacceptable except for the simplest cases. Most
of the time, you need to orchestrate the workings of the inherited classes carefully to
obtain the desired behavior.
When using multiple inheritance, one can achieve some pretty flexible orchestration by writing member functions that call member functions of several base classes. So, what is the orchestration that is missing from multiple inheritance and present in templates?
Please note that not every disadvantage of multiple inheritance compared to templates goes as an answer here, but only a disadvantage in what Andei calls mechanics in the above quote. In particular, please make sure that you are not talking about one of the other two weaknesses of multiple inheritance listed by Andrei:
Type information. The base classes do not have enough type information to carry on
their tasks. For example, imagine you try to implement deep copy for your smart
pointer class by deriving from a DeepCopy base class. But what interface would DeepCopy
have? It must create objects of a type it doesn’t know yet.
State manipulation. Various behavioral aspects implemented with base classes must manipulate
the same state. This means that they must use virtual inheritance to inherit a
base class that holds the state. This complicates the design and makes it more rigid because
the premise was that user classes inherit library classes, not vice versa.

I think that what Alexandrescu is referring to in the "Mechanics" paragraph is expounded upon in the rest of the chapter. He's referring to how much more flexible policy-based class design is than inheritance-based class design, particularly with respect to the various ways in which policies can be implemented and combined - this in comparison to the single implementation and combination allowed through multiple inheritance.
For instance, when discussing the Creator policy he points out that the policy requires only a Create() method that returns a pointer to the class being created, but doesn't specify that it be virtual or non-static. And he shows several ways in which each policy could be created: a straightforward policy class such as (from section 1.5, skipping the MallocCreator and PrototypeCreator policies)
template<class T>
struct OpNewCreator
{
static T* Create()
{
return new T;
}
};
...
> //Library code
> template <class CreationPolicy>
> class WidgetManager:public CreationPolicy
> {
> ...
> };
...
// Application Code
typedef WidgetManager<OpNewCreator<Widget> > MyWidgetMgr;
or it could be implemented with template template parameters (section 1.5.1) as
//Library Code
template <template <class> class Creation Policy>
class WidgetManager : public CreationPolicy <Widget>
{
...
}
// Application Code
typedef WidgetManager<OpNewCreator> MyWidgetMgr
or (section 1.5.2) - implemented as a template member function:
struct OpNewCreator
{
template <class T>
static T* Create()
{
return new T;
}
}
These are examples of the flexible mechanics that are available in a template-based policy class solution and not available in a multiple inheritance solution. These particular examples are not maybe all that exciting, probably because they have to be short and simple for pedagogical reasons.

Related

Multiple inheritance and generic program

I am reading "Modern C++ Design: Generic Programming and Design Patterns Applied" by Andrei Alex., just started. At page 6, it has the following critcism of multiple inheritance:
The problems with assembling separate features by using multiple inheritance are as follows:
...
Type information. The base classes do not have enough type
information to carry out their tasks. For example, imagine you try to
implement deep copy for your smart pointer class by deriving from a DeepCopy
base class. What interface would DeepCopy have? It must create objects of a
type it doesn't know yet.
I am wondering if this particular critique is flawed.
Interface driven design normally has base class a pure virtual class and the child class implements the interfaces. Take DeepCopy as example, I would do this:
struct DeepCopy
{
virtual void copy(DeepCopy *src) = 0;
};
class MyClass : public DeepCopy, public AnotherIntf
{
public:
virtual void copy(DeepCopy *src);
};
In this example, MyClass is the implementer and it is a real class.
Maybe I miss the point of Andrei's critique here.
What do you think?
It was my understanding that Alexandrescu was speaking of an external copying facility here, not an intrusive one that requires modification of the classes being copied. The proper way to implement deep copy for a given class may differ based on the class's implementation, so without a way to provide type information to the external copying facility you can't select the proper approach.
Deep copy may not be a great example here -- his chapters on generalized functors, smart pointers, and multiple dispatch are what I would consider better real-world examples of his policy-based design.

Why not abstract policies?

When implementing policies, one needs to follow a specific interface. From what I understand the policies have to be able to replace each other. In modern c++ book, Ch 1.5 3 policies have the same interface "T* Create() {}". Why is there no need to abstract it. It would be important if there are number of interfaces that policies should have. from I understand abstract class gives a recipe for which interfaces should be in concrete classes (the policy classes). In the Wikipedia example "using" defines which interfaces the policy should have but it's not through an abstract class. Isn't the point of abstract class to make sure that derived classes have the required interfaces?
what am I missing?
There is a difference in that an interface using an abstract base class has virtual functions providing runtime polymorphism.
The policies are used to provide compile time polymorphism for the templates. The compiler will notice if your policy class has a T* Create() or not. If it doesn't, you will get a compile time error when trying to use it.
I've never actually used policy-based design in practice and it's ages since I coded in C++, but here's my interpretation. As you've pointed out, the host class can enforce constraints on the policies used with it, either through interfaces, or through something like using output_policy::Print;, as the wiki example depicts.
An advantage (or difference) of the using method is that it's less proactively restrictive and less rigid, as policies have an implied contract which is represented directly by the code which uses them. In the using example, given the current state of the code, the output_policy implementation need only implement a method called Print which returns anything and takes whatever language_policy::Message() returns (in this case, all language_policies return a std::string). This is a little closer to duck typing.
One disadvantage is that the implied contract disappears once the code goes away. Another disadvantage is that policies have some level of dependency on each other. As a very contrived example, if one output_policy has a non-generic Print method which prints only strings, it cannot be used with a language_policy which prints only integers.
I don't see why you can't add policy interfaces if needed. One example is where the HelloWorld class might want to constrain the output_policy so that it prints strings and nothing else. You could achieve this by coding something like the below - note that you'd have to use SFINAE to enforce that output_policy<std::string> actually implements OutputPolicyInterface<std::string>.
template<typename message_type>
class OutputPolicyInterface
{
virtual void Print( message_type message ) = 0;
};
template <template<class> class output_policy, typename language_policy>
class HelloWorld : public output_policy<std::string>, public language_policy
{
public:
void Run()
{
Print( Message() );
//Print(2); won't work anymore
}
};

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.
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.
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.

Design of pointer container template

I would like to write a "versatile" class representing the general container storing pointers. Should I use public inheritance or containment?
template <class T>
class List : public std::vector <T *>
{
//...
}
Or
template <class T>
class List
{
private:
std::vector <T *> items;
//...
}
May some problems occur with abstract classes (i.e. virtual destructor)?
If neither proposal is appropriate, what design should I follow (and could you include a short example)?
This is already done for you with Boost's pointer containers.
I do not like boost so I would like to use only C++ 0x00 standard :-).
  — Ian (comment)
If you still want to re-invent these classes, look at the design decisions they made. In particular, they don't inherit from other containers as your first code does.
In fact, just copy the code right out from Boost. This is a header-only library and should be straight-forward (i.e. few implementation-specific workarounds). Boost's license is very liberal, not even requiring you to mention Boost when distributing compiled programs.
How about:
typedef std::vector<boost::shared_ptr<T> > List;
That is, I think it's better to use a resource managing pointer within regular container classes than to reinvent each of the container classes to add resource management capability.
private inheritance is a common tactic for creating classes that are implemented in terms of another. Code that uses the class can't tell that the derived class is derived from a private base, so you won't end up in the sorts of situations that might ordinarily require a virtual destructor.
Use using to import members from the private base to the derived class. For example:
template<class T>
class List:
private std::vector<T>
{
public:
using std::vector<T>::operator[];
using std::vector<T>::size;
};
This is a bit crude, but it gives you some flexibility. You can start out by using private inheritance, and this saves you some typing compared to writing forwarding functions, but you can still write alternative implementations long-hand as required. And then, if/when this becomes inappropriate, you can change the implementation style -- perhaps have a vector as a member, for example, or maybe do everything by hand -- safe in the knowledge that client code won't need to change.
This is ideal for situations where you're pretty sure you'll eventually need a non-standard type of container, but have an existing container type that mostly fits the bill for now. And it's a better medium-term solution than a typedef, because there's no risk of client code accidentally (or on purpose...) using the two types interchangeably.

Template or abstract base class?

If I want to make a class adaptable, and make it possible to select different algorithms from the outside -- what is the best implementation in C++?
I see mainly two possibilities:
Use an abstract base class and pass concrete object in
Use a template
Here is a little example, implemented in the various versions:
Version 1: Abstract base class
class Brake {
public: virtual void stopCar() = 0;
};
class BrakeWithABS : public Brake {
public: void stopCar() { ... }
};
class Car {
Brake* _brake;
public:
Car(Brake* brake) : _brake(brake) { brake->stopCar(); }
};
Version 2a: Template
template<class Brake>
class Car {
Brake brake;
public:
Car(){ brake.stopCar(); }
};
Version 2b: Template and private inheritance
template<class Brake>
class Car : private Brake {
using Brake::stopCar;
public:
Car(){ stopCar(); }
};
Coming from Java, I am naturally inclined to always use version 1, but the templates versions seem to be preferred often, e.g. in STL code? If that's true, is it just because of memory efficiency etc (no inheritance, no virtual function calls)?
I realize there is not a big difference between version 2a and 2b, see C++ FAQ.
Can you comment on these possibilities?
This depends on your goals. You can use version 1 if you
Intend to replace brakes of a car (at runtime)
Intend to pass Car around to non-template functions
I would generally prefer version 1 using the runtime polymorphism, because it is still flexible and allows you to have the Car still have the same type: Car<Opel> is another type than Car<Nissan>. If your goals are great performance while using the brakes frequently, i recommend you to use the templated approach. By the way, this is called policy based design. You provide a brake policy. Example because you said you programmed in Java, possibly you are not yet too experienced with C++. One way of doing it:
template<typename Accelerator, typename Brakes>
class Car {
Accelerator accelerator;
Brakes brakes;
public:
void brake() {
brakes.brake();
}
}
If you have lots of policies you can group them together into their own struct, and pass that one, for example as a SpeedConfiguration collecting Accelerator, Brakes and some more. In my projects i try to keep a good deal of code template-free, allowing them to be compiled once into their own object files, without needing their code in headers, but still allowing polymorphism (via virtual functions). For example, you might want to keep common data and functions that non-template code will probably call on many occasions in a base-class:
class VehicleBase {
protected:
std::string model;
std::string manufacturer;
// ...
public:
~VehicleBase() { }
virtual bool checkHealth() = 0;
};
template<typename Accelerator, typename Breaks>
class Car : public VehicleBase {
Accelerator accelerator;
Breaks breaks;
// ...
virtual bool checkHealth() { ... }
};
Incidentally, that is also the approach that C++ streams use: std::ios_base contains flags and stuff that do not depend on the char type or traits like openmode, format flags and stuff, while std::basic_ios then is a class template that inherits it. This also reduces code bloat by sharing the code that is common to all instantiations of a class template.
Private Inheritance?
Private inheritance should be avoided in general. It is only very rarely useful and containment is a better idea in most cases. Common case where the opposite is true when size is really crucial (policy based string class, for example): Empty Base Class Optimization can apply when deriving from an empty policy class (just containing functions).
Read Uses and abuses of Inheritance by Herb Sutter.
The rule of thumb is:
1) If the choice of the concrete type is made at compile time, prefer a template. It will be safer (compile time errors vs run time errors) and probably better optimized.
2) If the choice is made at run-time (i.e. as a result of a user's action) there is really no choice - use inheritance and virtual functions.
Other options:
Use the Visitor Pattern (let external code work on your class).
Externalize some part of your class, for example via iterators, that generic iterator-based code can work on them. This works best if your object is a container of other objects.
See also the Strategy Pattern (there are c++ examples inside)
Templates are a way to let a class use a variable of which you don't really care about the type. Inheritance is a way to define what a class is based on its attributes. Its the "is-a" versus "has-a" question.
Most of your question has already been answered, but I wanted to elaborate on this bit:
Coming from Java, I am naturally
inclined to always use version 1, but
the templates versions seem to be
preferred often, e.g. in STL code? If
that's true, is it just because of
memory efficiency etc (no inheritance,
no virtual function calls)?
That's part of it. But another factor is the added type safety. When you treat a BrakeWithABS as a Brake, you lose type information. You no longer know that the object is actually a BrakeWithABS. If it is a template parameter, you have the exact type available, which in some cases may enable the compiler to perform better typechecking. Or it may be useful in ensuring that the correct overload of a function gets called. (if stopCar() passes the Brake object to a second function, which may have a separate overload for BrakeWithABS, that won't be called if you'd used inheritance, and your BrakeWithABS had been cast to a Brake.
Another factor is that it allows more flexibility. Why do all Brake implementations have to inherit from the same base class? Does the base class actually have anything to bring to the table? If I write a class which exposes the expected member functions, isn't that good enough to act as a brake? Often, explicitly using interfaces or abstract base classes constrain your code more than necessary.
(Note, I'm not saying templates should always be the preferred solution. There are other concerns that might affect this, ranging from compilation speed to "what programmers on my team are familiar with" or just "what I prefer". And sometimes, you need runtime polymorphism, in which case the template solution simply isn't possible)
this answer is more or less correct. When you want something parametrized at compile time - you should prefer templates. When you want something parametrized at runtime, you should prefer virtual functions being overridden.
However, using templates does not preclude you from doing both (making the template version more flexible):
struct Brake {
virtual void stopCar() = 0;
};
struct BrakeChooser {
BrakeChooser(Brake *brake) : brake(brake) {}
void stopCar() { brake->stopCar(); }
Brake *brake;
};
template<class Brake>
struct Car
{
Car(Brake brake = Brake()) : brake(brake) {}
void slamTheBrakePedal() { brake.stopCar(); }
Brake brake;
};
// instantiation
Car<BrakeChooser> car(BrakeChooser(new AntiLockBrakes()));
That being said, I would probably NOT use templates for this... But its really just personal taste.
Abstract base class has on overhead of virtual calls but it has an advantage that all derived classes are really base classes. Not so when you use templates – Car<Brake> and Car<BrakeWithABS> are unrelated to each other and you'll have to either dynamic_cast and check for null or have templates for all the code that deals with Car.
Use interface if you suppose to support different Break classes and its hierarchy at once.
Car( new Brake() )
Car( new BrakeABC() )
Car( new CoolBrake() )
And you don't know this information at compile time.
If you know which Break you are going to use 2b is right choice for you to specify different Car classes. Brake in this case will be your car "Strategy" and you can set default one.
I wouldn't use 2a. Instead you can add static methods to Break and call them without instance.
Personally I would allways prefer to use Interfaces over templates because of several reasons:
Templates Compiling&linking errors are sometimes cryptic
It is hard to debug a code that based on templates (at least in visual studio IDE)
Templates can make your binaries bigger.
Templates require you to put all its code in the header file , that makes the template class a bit harder to understand.
Templates are hard to maintained by novice programmers.
I Only use templates when the virtual tables create some kind of overhead.
Ofcourse , this is only my self opinion.