STL containers take two template arguments, the type T
inside the container and the allocator (which defaults to std::allocator<T>
).
Therefore to write a function that takes any STL-like container, you have to do it like in this example function:
/** * Convert any STL-like container to a std::vector. */ template<template<typename, typename> typename Container, typename T, typename Allocator> std::vector ToVector(const Container<T, Allocator>& args) { std::vector ret; ret.reserve(args.size()); for(const T& arg : args) { ret.push_back(arg); } return ret; }
This function can take any STL-like container like std::list
, std::vector
and also STL-compatible containers from third-party libraries and convert it to a std::vector
.
Full example:
#include <list> // std::list #include <vector> // std::vector #include <iostream> // std::cout, std::endl using namespace std; /** * Convert any STL-like container to a std::vector. */ template<template<typename, typename> typename Container, typename T, typename Allocator> std::vector ToVector(const Container<T, Allocator>& args) { std::vector ret; ret.reserve(args.size()); for(const T& arg : args) { ret.push_back(arg); } return ret; } int main() { // Create list list myList; myList.push_back(2); myList.push_back(3); myList.push_back(5); // Convert to vector vector myVector = ToVector(myList); // Print vector - should print 2, 3 & 5 for(int val : myVector) { cout << val << endl; } }
Thanks to Jesse Good on StackOverflow for publishing hints on how to solve this problem. However, his version only works with STL containers that use std::allocator
and not with STL containers without custom allocators. In my experience it’s very rare that you have to use a custom allocator, but if you do, it’s very hard to debug why the template doesn’t match.