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.
Related
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.
Is there any hack I could use to do this:
template <class TYPE>
class Hello
{
TYPE _var;
};
I would like a way to store
Hello<int> intHello and Hello<char*> charHello
into the same Container such as a Queue / List.
No, because they are different and completely unrelated types.
You can, however, use inheritance and smart pointers:
class HelloBase
{
public:
virtual ~HelloBase();
}
template <class TYPE>
class Hello : public HelloBase
{
TYPE _var;
}
std::vector<boost::shared_ptr<HelloBase> > v;
shared_ptr may be supported by your implementation either in the std::tr1 or std namespace; you'd have to check.
Yes, sort of -- but you probably don't want to. Even though they start from the same template, Hello<int> and Hello<char *> are completely separate and unrelated types. A collection that includes both is heterogeneous, with all the problems that entails.
If you insist on doing this anyway, to do it reasonably cleanly, you'd typically create something like a queue/list of Boost::any.
First of all, the real question: what are you trying to achieve (at a higher level) ?
Now, for this peculiar question there is a number of alternative. Containers cannot store heterogeneous data, so you can:
give all Hello<T> a common base class and add virtual methods, then use pointers, take care of memory ownership (unique_ptr or boost::ptr_list would be great)
if there is a precise set of types, use boost::variant, it's statically checked so you have reasonable guarantees
else you should consider wrapping it into a storage class which would use boost::any under the covers
The common base class is the usual approach in this situation. If there is no reason to have polymorphism, then use preferably variant and if nothing else any.
While designing an interface for a class I normally get caught in two minds whether should I provide member functions which can be calculated / derived by using combinations of other member functions. For example:
class DocContainer
{
public:
Doc* getDoc(int index) const;
bool isDocSelected(Doc*) const;
int getDocCount() const;
//Should this method be here???
//This method returns the selected documents in the contrainer (in selectedDocs_out)
void getSelectedDocs(std::vector<Doc*>& selectedDocs_out) const;
};
Should I provide this as a class member function or probably a namespace where I can define this method? Which one is preferred?
In general, you should probably prefer free functions. Think about it from an OOP perspective.
If the function does not need access to any private members, then why should it be given access to them? That's not good for encapsulation. It means more code that may potentially fail when the internals of the class is modified.
It also limits the possible amount of code reuse.
If you wrote the function as something like this:
template <typename T>
bool getSelectedDocs(T& container, std::vector<Doc*>&);
Then the same implementation of getSelectedDocs will work for any class that exposes the required functions, not just your DocContainer.
Of course, if you don't like templates, an interface could be used, and then it'd still work for any class that implemented this interface.
On the other hand, if it is a member function, then it'll only work for this particular class (and possibly derived classes).
The C++ standard library follows the same approach. Consider std::find, for example, which is made a free function for this precise reason. It doesn't need to know the internals of the class it's searching in. It just needs some implementation that fulfills its requirements. Which means that the same find() implementation can work on any container, in the standard library or elsewhere.
Scott Meyers argues for the same thing.
If you don't like it cluttering up your main namespace, you can of course put it into a separate namespace with functionality for this particular class.
I think its fine to have getSelectedDocs as a member function. It's a perfectly reasonable operation for a DocContainer, so makes sense as a member. Member functions should be there to make the class useful. They don't need to satisfy some sort of minimality requirement.
One disadvantage to moving it outside the class is that people will have to look in two places when the try to figure out how to use a DocContainer: they need to look in the class and also in the utility namespace.
The STL has basically aimed for small interfaces, so in your case, if and only if getSelectedDocs can be implemented more efficiently than a combination of isDocSelected and getDoc it would be implemented as a member function.
This technique may not be applicable anywhere but it's a good rule of thumbs to prevent clutter in interfaces.
I agree with the answers from Konrad and jalf. Unless there is a significant benefit from having "getSelectedDocs" then it clutters the interface of DocContainer.
Adding this member triggers my smelly code sensor. DocContainer is obviously a container so why not use iterators to scan over individual documents?
class DocContainer
{
public:
iterator begin ();
iterator end ();
// ...
bool isDocSelected (Doc *) const;
};
Then, use a functor that creates the vector of documents as it needs to:
typedef std::vector <Doc*> DocVector;
class IsDocSelected {
public:
IsDocSelected (DocContainer const & docs, DocVector & results)
: docs (docs)
, results (results)
{}
void operator()(Doc & doc) const
{
if (docs.isDocSelected (&doc))
{
results.push_back (&doc);
}
}
private:
DocContainer const & docs;
DocVector & results;
};
void foo (DocContainer & docs)
{
DocVector results;
std :: for_each (docs.begin ()
, docs.end ()
, IsDocSelected (docs, results));
}
This is a bit more verbose (at least until we have lambdas), but an advantage to this kind of approach is that the specific type of filtering is not coupled with the DocContainer class. In the future, if you need a new list of documents that are "NotSelected" there is no need to change the interface to DocContainer, you just write a new "IsDocNotSelected" class.
The answer is proabably "it depends"...
If the class is part of a public interface to a library that will be used by many different callers then there's a good argument for providing a multitude of functionality to make it easy to use, including some duplication and/or crossover. However, if the class is only being used by a single upstream caller then it probably doesn't make sense to provide multiple ways to achieve the same thing. Remember that all the code in the interface has to be tested and documented, so there is always a cost to adding that one last bit of functionality.
I think this is perfectly valid if the method:
fits in the class responsibilities
is not too specific to a small part of the class clients (like at least 20%)
This is especially true if the method contains complex logic/computation that would be more expensive to maintain in many places than only in the 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.
It looks like I had a fundamental misunderstanding about C++ :<
I like the polymorphic container solution. Thank you SO, for bringing that to my attention :)
So, we have a need to create a relatively generic container type object. It also happens to encapsulate some business related logic. However, we need to store essentially arbitrary data in this container - everything from primitive data types to complex classes.
Thus, one would immediately jump to the idea of a template class and be done with it. However, I have noticed C++ polymorphism and templates do not play well together. Being that there is some complex logic that we are going to have to work, I would rather just stick with either templates OR polymorphism, and not try to fight C++ by making it do both.
Finally, given that I want to do one or the other, I would prefer polymorphism. I find it much easier to represent constraints like "this container contains Comparable types" - a la java.
Bringing me to the topic of question: At the most abstract, I imagine that I could have a "Container" pure virtual interface that has something akin to "push(void* data) and pop(void* data)" (for the record, I am not actually trying to implement a stack).
However, I don't really like void* at the top level, not to mention the signature is going to change every time I want to add a constraint to the type of data a concrete container can work with.
Summarizing: We have relatively complex containers that have various ways to retrieve elements. We want to be able to vary the constraints on the elements that can go into the containers. Elements should work with multiple kinds of containers (so long as they meet the constraints of that particular container).
Edit: I should also mention that the containers themselves need to be polymorphic. That is my primary reason for not wanting to use templated C++.
So - should I drop my love for Java type interfaces and go with templates? Should I use void* and statically cast everything? Or should I go with an empty class definition "Element" that declares nothing and use that as my top level class in the "Element" hierarchy?
One of the reasons why I love stack overflow is that many of the responses provide some interesting insight on other approaches that I hadn't not have even considered. So thank you in advance for your insights and comments.
You can look at using a standard container of boost::any if you are storing truly arbitrary data into the container.
It sounds more like you would rather have something like a boost::ptr_container where anything that can be stored in the container has to derive from some base type, and the container itself can only give you reference's to the base type.
The simple thing is to define an abstract base class called Container, and subclass it for each kind of item you may wish to store. Then you can use any standard collection class (std::vector, std::list, etc.) to store pointers to Container. Keep in mind, that since you would be storing pointers, you would have to handle their allocation/deallocation.
However, the fact that you need a single collection to store objects of such wildly different types is an indication that something may be wrong with the design of your application. It may be better to revisit the business logic before you implement this super-generic container.
Polymorphism and templates do play very well together, if you use them correctly.
Anyway, I understand that you want to store only one type of objects in each container instance. If so, use templates. This will prevent you from storing the wrong object type by mistake.
As for container interfaces: Depending on your design, maybe you'll be able to make them templated, too, and then they'll have methods like void push(T* new_element). Think of what you'll know about the object when you want to add it to a container (of an unknown type). Where will the object come from in the first place? A function that returns void*? Do you know that it'll be Comparable? At least, if all stored object classes are defined in your code, you can make them all inherit from a common ancestor, say, Storable, and use Storable* instead of void*.
Now if you see that objects will always be added to a container by a method like void push(Storable* new_element), then really there will be no added value in making the container a template. But then you'll know it should store Storables.
Can you not have a root Container class that contains elements:
template <typename T>
class Container
{
public:
// You'll likely want to use shared_ptr<T> instead.
virtual void push(T *element) = 0;
virtual T *pop() = 0;
virtual void InvokeSomeMethodOnAllItems() = 0;
};
template <typename T>
class List : public Container<T>
{
iterator begin();
iterator end();
public:
virtual void push(T *element) {...}
virtual T* pop() { ... }
virtual void InvokeSomeMethodOnAllItems()
{
for(iterator currItem = begin(); currItem != end(); ++currItem)
{
T* item = *currItem;
item->SomeMethod();
}
}
};
These containers can then be passed around polymorphically:
class Item
{
public:
virtual void SomeMethod() = 0;
};
class ConcreteItem
{
public:
virtual void SomeMethod()
{
// Do something
}
};
void AddItemToContainer(Container<Item> &container, Item *item)
{
container.push(item);
}
...
List<Item> listInstance;
AddItemToContainer(listInstance, new ConcreteItem());
listInstance.InvokeSomeMethodOnAllItems();
This gives you the Container interface in a type-safe generic way.
If you want to add constraints to the type of elements that can be contained, you can do something like this:
class Item
{
public:
virtual void SomeMethod() = 0;
typedef int CanBeContainedInList;
};
template <typename T>
class List : public Container<T>
{
typedef typename T::CanBeContainedInList ListGuard;
// ... as before
};
First, of all, templates and polymorphism are orthogonal concepts and they do play well together. Next, why do you want a specific data structure? What about the STL or boost data structures (specifically pointer containter) doesn't work for you.
Given your question, it sounds like you would be misusing inheritance in your situation. It's possible to create "constraints" on what goes in your containers, especially if you are using templates. Those constraints can go beyond what your compiler and linker will give you. It's actually more awkward to that sort of thing with inheritance and errors are more likely left for run time.
Using polymorphism, you are basically left with a base class for the container, and derived classes for the data types. The base class/derived classes can have as many virtual functions as you need, in both directions.
Of course, this would mean that you would need to wrap the primitive data types in derived classes as well. If you would reconsider the use of templates overall, this is where I would use the templates. Make one derived class from the base which is a template, and use that for the primitive data types (and others where you don't need any more functionality than is provided by the template).
Don't forget that you might make your life easier by typedefs for each of the templated types -- especially if you later need to turn one of them into a class.
You might also want to check out The Boost Concept Check Library (BCCL) which is designed to provide constraints on the template parameters of templated classes, your containers in this case.
And just to reiterate what others have said, I've never had a problem mixing polymorphism and templates, and I've done some fairly complex stuff with them.
You could not have to give up Java-like interfaces and use templates as well. Josh's suggestion of a generic base template Container would certainly allow you do polymorphically pass Containers and their children around, but additionally you could certainly implement interfaces as abstract classes to be the contained items. There's no reason you couldn't create an abstract IComparable class as you suggested, such that you could have a polymorphic function as follows:
class Whatever
{
void MyPolymorphicMethod(Container<IComparable*> &listOfComparables);
}
This method can now take any child of Container that contains any class implementing IComparable, so it would be extremely flexible.