Alberth: Thanks for your reply. Spelling out what my templates actually are asking for helps... I find them very confusing.
template <class S>
void add(std::shared_ptr<S> system)
{
m_systems.insert(system);
}
They are a completely separate layer on top of normal C++.
That is,
void add(std::shared_ptr<S> system)
{
m_systems.insert(system);
}
Is a perfectly normal C++ function (as you deduced too), where S is an existing class, fully defined etc. So here you must obey all the normal rules you have elsewhere too, for an existing class S used in this code. So if you don't supply an argument to 'add', or use the 'insert' wrong, you get an error as usual.
The 'template' line forms a bridge between the 'S' you can assume to exist here, and a real class that you have. That can happen in 2 forms.
The first form is explicitly saying what 'S' is by adding "<MovementSystem>" behind a function name, like
add<MovementSystem>(..)
A somewhat weird place, but on the other hand, it has to go somewhere, and this is a pretty good place, as it reads nicely as "this is 'add' for class MovementSystem".
It does sort-of a local "typedef MovementSystem S;" for this one call.
The second form is implicitly like
std::shared_ptr<MovementSystem> p = std::make_shared<MovementSystem>(); // Probably incorrect, but it should make a 'p' value with the right type.
add(p);
You just call the function, and let the type system deduce that S of the 'add' is in fact 'MovementSystem' here.
The biggest 'weird' thing here is that an error can now also be caused by template parameters. As a result, errors with templates also dump all info on resolving their type parameters, which takes some time getting used to. That is what your "no instance of overloaded function "std::vector<_Ty, _Alloc>::insert [with _Ty=std::shared_ptr<System>, _Alloc=std::allocator<std::shared_ptr<System>>]" matches the argument list" error says. It dumps all the template parameters it can find with the type it believes should be used there. Since we normally never bother with allocators for the containers, it looks weird.
So when I initiate this template, I have to make sure I put a 'Type' inside the angle brackets (< >), but I also need the parameter... a bit like a normal function? So it would be equivalent to me writing (e.g. this is what it would generate):
Yep, plain simple normal function, just replace S by MovementSystem.
When I try your example using std::allocate_shared I receive the error: "no instance of function template "std::allocate_shared" matches the argument list". I will be honest I am a bit lost as to whats going on here.
Maybe you use a different C++ version, I copied it from the cppreference site, where it said c++11 iirc, so it's quite new. Maybe your compiler doesn't do that, or you didn't say you wanted c++11 or so.
It's however also possible I am wrong somewhere, I don't write enough C++ anymore :(
Am I using templates the right way for this? My idea is to create all my systems (by inheriting from the System base class) then just add them all like:
You have to fix the 'add' parameter for that to work. Unless you have an 'add' without parameter in mind here.
(Note this is similar to how the ECS framework entitiyx works)
I see lots of people here making these complicated ECS systems for some reason. I have never had the need for them yet, and I don't understand why everybody makes these highly complicated things.
Also, I believe doing what some other system does is not a good enough reason to pick that solution too. Your aim is probably different from their aim. Feel free to ignore me though :)
'virtual destructor in System': Thanks for picking this up. Just to clear my understanding, this will mean that my systems instances are cleaned up when my systems end?
It makes sure that "delete myMovementSystem;" will delete all subclasses of System in the proper order. Without it, it would just perform the destructor of MovementSystem, and nothing else.