Поскольку вы в любом случае делаете одну реализацию для каждого контейнера, вы можете делать перегрузки напрямую. Он будет работать на C ++ 11 и имеет то преимущество, что параметры шаблона легко доступны в каждой перегрузке.
template <class T, size_t N>
void func(const std::array<T,N>& c) {
std::cout << "array " << c.size() << '\n';
}
template <class T, class Alloc>
void func(const std::vector<T,Alloc>& c) {
std::cout << "vector " << c.size() << '\n';
}
template <class T, class Alloc>
void func(const std::list<T,Alloc>& c) {
std::cout << "list " << c.size() << '\n';
}
template <class Key, class T, class Comp, class Alloc>
void func(const std::map<Key,T,Comp,Alloc>& c) {
std::cout << "map " << c.size() << '\n';
}
template <class CharT, class Traits, class Alloc>
void func(const std::basic_string<CharT,Traits,Alloc>& c) {
std::cout << "basic_string " << c.size() << '\n';
}
// add more of the containers you aim to support here