Use templates for functions that accept a list of devices

To be compatible with both vector<Device*> and
vector<shared_ptr<Device>>
Update .gitignore