I am trying to implement a Priority Queue using a Vector template in C++. I am most comfortable with Java and want to mimic the idea of an Interface, where all objects that can use the Priority Queue are required to implement certain methods.
I know that C++ does not support Interfaces, however, someone suggested that by tapping into Multiple Inheritance this could be achieved by creating an Abstract Class and requiring some virtual functions.
I would like all objects that can use the Priority Queue to implement:
public:
int compareTo(Comparable &obj);
Here is a C++ Abstract Class that achieves this:
Comparable.h
class Comparable {
public:
Comparable();
~Comparable();
virtual int compareTo(Comparable &obj) = 0;
};
This works great, no errors are formed from supplying the Abstract Class to the Vector template:
vector<Comparable> *mElements = new vector<Comparable>(); // no error
It is not until I try to use polymorphism in a class that inherits from the Comparable class that I run into an issue. Because the Method signature receives a Comparable&, I am having trouble accessing the members of the class that extends Comparable:
int Event::compareTo(Comparable& obj) {
// Min-Heap - time of currentObject is less than e.mTime
Event e = (Event) obj; // Doesn't work - No C-style cast (can I make one and how?)
// if I trying obj.mTime, this won't work because it is not a member of the Comparable class
if (mTime < e.mTime) return Delta::NEGATIVE_CHANGE;
if (mTime > e.mTime) return Delta::POSITIVE_CHANGE;
return return Delta::NO_CHANGE;
}
All I need to do is compare the time in this example, but I would like to design the class so that clients only have to inherit from the Comparable class and implement the one method for use of the priority queue.
Thanks for any help in advanced!
You are searching for dinamic_cast
http://en.cppreference.com/w/cpp/language/dynamic_cast
dinamic_cast has a ugly name cause you shouldn't use it too much. In this case, you don't need it.
First, in C++ you can overload operators (<, >, ==...). If these operators doesn't exist, the class can't be compared. It's more natural and easy for compare :)
Second, you can use a generic template:
template<class T>
class Comparable {
public:
Comparable();
~Comparable();
virtual int compareTo(T &obj) = 0;
};
class event : public Comparable<event> {
//...
public:
int compareTo(event &e) override;
};
You can detect wrong types in compile time, you don't need cast in execution time :)
override is one c++11 flag for compiler: "This function should override one parent function, check it". You can remove it freely if you don't use C++11
Actually, you don't need the Comparable class at all, if the PriorityQueue class is a template itself. It will compile for types that implement compareTo and won't compile for types that don't implement it.
template <class T>
class PriorityQueue {
...
void someMethod(const T& obj) {
if (someOtherObj.compareTo(obj)) {
...
}
}
...
}
As I previously said in a comment, the STL ordered containers use functors instead of requiring some specific interface for their elements. Easier than using a functor is using < to compare objects:
if (someOtherObj < obj) {
That Comparable class actually fits the ideia of a concept (C++14), not an abstract interface. It helps to clarify for a template class/function what is its required interface, but concepts are a very new feature of the C++ language and not widely supported or even known.
Related
In C# I can define this:
public interface BaseObject
{
int GetValue();
}
public class Test<T> where T : BaseClass
{
T BaseObject;
}
which means I know that I can alwaysa call BaseObject.GetValue() / BaseObject->GetValue(); because I know that the baseobject has this method.
Is there a similiar way to do this in C++? So that I can define an interface that multiple classes can inherit and a class that can take advantage of this.
Templates, which are even more powerful than C# generics (not to say they are necessarily better, just different).
template<class T>
class foo
{
public:
int whatever()
{
return obj.GetValue();
}
private:
T obj;
};
A separate class is created for each template argument you use. If you provide a template type which would result in an error you will know at compile time.
You're asking about C++ concepts, a way to specify requirements for template parameters. They were proposed during the work on C++11, but proved complicated enough that they weren't done in time. But they've just been delayed, not forgotten.
In the meantime, duck typing remains very powerful, and it will catch when you pass a template parameter that doesn't have the required interface. It just won't report the problem as neatly.
As a workaround, a simple way to check the constraint you showed takes advantage of the fact that pointer conversions are implicit only when upcasting:
public class Test<T> where T : BaseClass
{
static T* enforcement_helper = 0;
static BaseClass* enforce_inheritance_constraint = enforcement_helper;
};
Depending on how new your compiler is, you may need to put those lines inside a special member function (destructor is good, because it's almost always processed).
But you should only check constraints in order to improve error messages (by causing the failure in a clearly commented section of code). C++ templates are duck typed, and they will work with any template parameters that provide the required operations. No formal "interface" is required.
Say I have two different objects that are completely different, Sprite and PhysicsData.
I write an empty base class and a container class that can push and remove objects to/from a container.
I create two of these containers to store the two different objects - Sprite and PhysicsData.
(Different objects aren't together in the same class)
class base
{
};
class ContainerManager
{
public:
std::vector<base*> list;
void Push(base *object);
void Remove(base *object);
};
class PhysicsData : public base
{
void applyGravity();
};
class Sprite : public base
{
void Draw();
};
ContainerManager SpriteContainer;
ContainerManager PhysicsDataContainer;
Sprite aSprite;
SpriteContainer.Push(&aSprite);
PhysicsData SomeData;
PhysicsDataContainer.Push(&SomeData);
Is this the way that this should bet done?
This is not a C++ way. You should use templates.
For you to know, STL (which you are calling to when using std:: namespace prefix) is, actually, Standard Template Library :). A lot of template classes are already there, e.g. for the push / remove operations see std::list<T>
You use it like this:
std::list<Sprite> SpriteContainer;
std::list<PhysicsData> PhysicsDataContainer;
and so on.
There is a cool guide about C++ templates, if you still want to do your own class for some more functionality.
And there is a reference to std::list, (i don't think i need to explain the usage of std::vector for you) if the question was the actual thing you've wanted to do.
You're having Templates in C++ and still worrying about having a common base class for a trivial container??
template <class T>
class Container{
private:
vector<T> list;
public:
void Push(T data);
T Pop();
};
If you put a single virtual function into the base class, you'll be able to use dynamic_cast to get back the proper pointer if you mix different types in the same container. A virtual destructor would be a good idea because then you could delete the object if it were dynamically allocated, without having to cast it back to the original pointer.
If you're not going to mix types within a single container, I agree with dreamzor that a template class would be better. That's the way all the standard containers are implemented.
That looks like technically correct code but you are not doing any type checking. So as you can see PhysicsData is showing up in your SpriteContainer. You probably do not want this.
There is more than one way to keep PhysicsData out of your SpriteContainer. One way is to use templates. With templates you would state what type of base objects the container should work with at compile time.
Another method is to inherit from your ContainerManager two types of ContainerManagers, one called PhysicsContainerManager and one called SpriteContainerManager. These two child classes can do type check to verify that the objects being passed are in fact either a SpriteContainer or a PhisicsData. This link shows how to do type check in c++ C++ equivalent of instanceof
thanks
jose
I am working with an abstract base class implementing a set of system tests. In simplified form, the class declaration is:
class Test_Class
{
Test_Class();
~Test_Class();
Run_Test(void * param_set = NULL) = 0;
}
The base class requires the implementation of the Run_Test function which allows a user to pass in an arbitrary data structure as a void pointer and cast it to the appropriate type inside the body of Run_Test in a child class, in order to allow different tests to use different data structures, e.g. a float in one test vs a list of ints in another.
This is cumbersome and seems like an incredibly C-like way of doing things. Is there a better way of using inheritance or other language utilities?
Note: Due to customer constraints, this program is not allowed access to the STL or the Boost libraries.
Yes. User doesn't pass in an arbitary data structure but can make an arbitrary data structure by extending your base class.
class Test_Class {
Run_Test(const Config& config);
};
client code:
class MyConfig : public Config {
//...
};
Another option is templates. You can accomplish many common tasks with either, I'm not sure which is ideal in this situation so I'll leave it to other answers or to you to research that if you go this route.
If you want a set of tests, use std::vector<std::function<void()>> tests; and then you can simply tests.push_back([=] { do_test(the_args, I_captured, from_local, scope); });.
You can do similar tricks with std::bind if your compiler doesn't support lambdas.
There's no need for you, the end-user, to write your own generic function interface. It already has been done.
Edit: Yes, you're going to end up with some C-style garbage if you do not A) re-implement the wheels provided by Boost or the STL or B) use the existing wheels provided by Boost or STL. There is no magical third choice between "Write own good code" or "Use other people's good code" which still results in good code.
I dont remember is it possible/how to make argument detection for function inside class so maybe this will do:
class Test_Class {
public:
template <typename T>
void Run_Test(T p) {
}
};
template <class T>
void tester(Test_Class t, T p) {
t.Run_Test<T>(p);
}
int main() {
Test_Class p;
int a = 5;
tester(p, a);
}
I have a base class representing an item with some common properties (name, a few flags, etc):
class AbstractItem;
class MacroDefinition : public AbstractItem;
I also have a templatized class which manages collections of these items, also taking care of common functionality like loading them from XML files on disk:
template <class ItemT>
class AbstractItemManager
{
public:
AbstractItemManager();
ItemT* GetAt(int index);
vector<ItemT*> Get(...);
private:
vector<ItemT*> mItems;
};
For any given type of AbstractItem, I can create a manager class of that appropriate type, have the base functionality handled for me, and then layer functionality specific to that type on top of that:
class MacroManager : public AbstractItemManager<MacroDefinition>
{
public:
MacroManager():AbstractItemManager<MacroDefinition>();
};
The fact that the manager class takes the type of item as a template parameter means I can make calls like this, both within MacroManager and externally, and get items of the appropriate type without having to blindly cast pointers all over the place.
MacroManager* macroManager = new MacroManager();
Macro* macro = macroManager->GetAt(2);
Now I'm implementing another class. I want to be able to pass it a reference to an AbstractItemManager so that I can access the list of items in any given manager class. However, I need to make the compiler understand that ItemT will always be derived from AbstractItem. I'd like to be able to do something like this:
class FavoriteAbstractItemList
{
public:
FavoriteAbstractItemList(AbstractItemManager* manager)
:mManager(manager)
{
vector<AbstractItem*> items = mManager->Get(...);
...
}
private:
AbstractItemManager* mManager;
};
Consequently:
FavoriteAbstractItemList* list = new FavoriteAbstractItemList(macroManager);
Of course, this is invalid, because I'm not supplying a template argument to AbstractItemManager when I'm using it in FavoriteAbstractItemList. Because my manager subclasses (MacroManager etc.) have all different ItemT types, I'm stuck here.
I imagine that I could change my class hierarchy a bit, and this would work:
template<class ItemT>
class AbstractItemManager_Base;
class AbstractItemManager : public AbstractItemManager_Base<AbstractItem>;
class MacroManager : public AbstractItemManager;
But then the template argument ItemT would be set in stone as AbstractItem in MacroManager etc., so I'd have to explicitly cast all items within MacroManager to Macro and take care to ensure that only items of type Macro were be added to it.
This seems like it's probably a common problem, but not one that has a straightforward answer. I don't have too much hands-on experience with C++ templates, so I'd greatly appreciate being set straight on this issue. Given the tradeoffs I've presented, what's the most sensible way to accomplish what I'm looking for? Or am I approaching things the wrong way to begin with?
Thanks for all your helpful answers. I ended up going with the solution that you both proposed. It hadn't occurred to me that I could use a template type to override an already-defined base type, but the compile-time chicanery of C++ templates is something I'm slowly getting used to.
As for the vector problem, that's unfortunate, but I ended up going with one of the proposed solutions and creating a separate method in the templatized class that calls the original method and stuffs everything into a new vector<ItemT*> with a bunch of static casts. I'm sure that adds a little bit of overhead, but it's still far more elegant than my knee-jerk solution of abandoning templates entirely. The only thing I really lose is the ability to directly iterate over mItems in subclasses without a cast from AbstractItem* to Macro* (etc.), but I can certainly deal with that.
Here's the new class hierarchy, in essence:
class AbstractItemManager
{
public:
virtual AbstractItem* GetAt(int index);
vector<AbstractItem*> Get(...);
protected:
vector<AbstractItem*> mItems;
};
template <class ItemT>
class TemplatizedItemManager : public AbstractItemManager
{
public:
virtual ItemT* GetAt(int index);
std::vector<ItemT*> GetItems(...);
};
class MacroManager : public TemplatizedItemManager<Macro>;
Thanks again!
class AbstractItemManager_Base
{
public:
virtual AbstractItem* GetAt (int index) = 0;
};
template <class ItemT>
class AbstractItemManager : public AbstractItemManager_Base
{
ItemT* GetAt (int index); // works if ItemT derives from AbstractItem
};
Now you can use an AbstractItemManager_Base in FavoriteAbstractItemList.
Replacing vector<ItemT*> Get(...) is somewhat more involved. vector<AbstractItem*> is not compatible with vector<ItemT*>, for any ItemT. You can try to create your own container hierarchy, such that myvector<AbstractItem*> is somehow compatible with myvector<ItemT*>; or provide an iterator-based interface to your ItemManager so that it is a container; or just have two separate unrelated functions, one returning vector<ItemT*> and the other returning vector<AbstractItem*>.
You actually have two problems. The first one is aboutz GetAt. This has a simple solution: Don't template the base, template the derived:
class AbstractItem
{
// ...
};
class MacroDefintiion:
public AbstractItem
{
// ...
};
class AbstractItemMananger
{
public:
virtual AbstractItem* GetAt(int) = 0;
// ...
};
template<typename Item> class SpecificAbstractItemManager
{
public:
Item* GetAt(); // covariant return type
// ...
};
class MacroManager: public SpecificAbstractItemManager
{
// ...
};
The second one is your Get method. That one is problematic because std::vector<Derived*> and std::vector<Base*> are unrelated classes, as far as C++ is concerned, and therefore you cannot use them for covariant return types.
Probably the best solution here is to have two functions in the derived class, one returning a std::vector<AbstractItem> (inherited from and overriding the base class function) and another one returning an std::vector<Item*>.
That is, in AbstractItemManager you have
std::vector<AbstractItem*> Get() = 0;
and in SpecificAbstractItemManager<Item> you have e.g.
std::vector<AbstractItem*> Get() { return GetSpecific(); }
std::vector<Item*> GetSpecific();
Mixins and function templates are two different ways of providing a behavior to a wide set of types, as long as these types meet some requirements.
For example, let's assume that I want to write some code that allows me to save an object to a file, as long as this object provides a toString member function (this is a rather silly example, but bear with me). A first solution is to write a function template like the following:
template <typename T>
void toFile(T const & obj, std::string const & filename)
{
std::ofstream file(filename);
file << obj.toString() << '\n';
}
...
SomeClass o1;
toFile(o1, "foo.txt");
SomeOtherType o2;
toFile(o2, "bar.txt");
Another solution is to use a mixin, using CRTP:
template <typename Derived>
struct ToFile
{
void toFile(std::string const & filename) const
{
Derived * that = static_cast<Derived const *>(this);
std::ofstream file(filename);
file << that->toString() << '\n';
}
};
struct SomeClass : public ToFile<SomeClass>
{
void toString() const {...}
};
...
SomeClass o1;
o.toFile("foo.txt");
SomeOtherType o2;
o2.toFile("bar.txt");
What are the pros and cons of these two approaches? Is there a favored one, and if so, why?
The first approach is much more flexible, as it can be made to work with any type that provides any way to be converted to a std::string (this can be achieved using traits-classes) without the need to modify that type. Your second approach would always require modification of a type in order to add functionality.
Pro function templates: the coupling is looser. You don't need to derive from anything to get the functionality in a new class; in your example, you only implement the toString method and that's it. You can even use a limited form of duck typing, since the type of toString isn't specified.
Pro mixins: nothing, strictly; your requirement is for something that works with unrelated classes and mixins cause them to be become related.
Edit: Alright, due to the way the C++ type system works, the mixin solution will strictly produce unrelated classes. I'd go with the template function solution, though.
I would like to propose an alternative, often forgotten because it is a mix of duck-typing and interfaces, and very few languages propose this feat (note: very close to Go's take to interfaces actually).
// 1. Ask for a free function to exist:
void toString(std::string& buffer, SomeClass const& sc);
// 2. Create an interface that exposes this function
class ToString {
public:
virtual ~ToString() {}
virtual void toString(std::string& buffer) const = 0;
}; // class ToString
// 3. Create an adapter class (bit of magic)
template <typename T>
class ToStringT final: public ToString {
public:
ToStringT(T const& t): t(t) {}
virtual void toString(std::string& buffer) const override {
toString(buffer, t);
}
private:
T t; // note: for reference you need a reference wrapper
// I won't delve into this right now, suffice to say
// it's feasible and only require one template overload
// of toString.
}; // class ToStringT
// 4. Create an adapter maker
template <typename T>
ToStringT<T> toString(T const& t) { return std::move(ToStringT<T>(t)); }
And now ? Enjoy!
void print(ToString const& ts); // aka: the most important const
int main() {
SomeClass sc;
print(toString(sc));
};
The two stages is a bit heavyweight, however it gives an astonishing degree of functionality:
No hard-wiring data / interface (thanks to duck-typing)
Low-coupling (thanks to abstract classes)
And also easy integration:
You can write an "adapter" for an already existing interface, and migrate from an OO code base to a more agile one
You can write an "interface" for an already existing set of overloads, and migrate from a Generic code base to a more clustered one
Apart from the amount of boiler-plate, it's really amazing how you seamlessly pick advantages from both worlds.
A few thoughts I had while writing this question:
Arguments in favor of template functions:
A function can be overloaded, so third-party and built-in types can be handled.
Arguments in favor of mixins:
Homogeneous syntax: the added behavior is invoked like any other member functions. However, it is well known that the interface of a C++ class includes not only its public member functions but also the free functions that operates on instances of this type, so this is just an aesthetic improvement.
By adding a non-template base class to the mixins, we obtain an interface (in the Java/C# sense) that can be use to handle all objects providing the behavior. For example, if we make ToFile<T> inherits from FileWritable (declaring a pure virtual toFile member function), we can have a collection of FileWritable without having to resort to complicated heterogeneous data structures.
Regarding usage, I'd say that function templates are more idiomatic in C++.