Кратко:

Вариативные шаблоны позволяют шаблону принимать другой шаблон в качестве аргумента. Это особенно полезно для создания контейнеров или функций, которые могут работать с любыми шаблонами.

Синтаксис

template <template <typename T> class Container>
class MyClass {
    // ...
};

Пример кода

Пример 1: Шаблонный класс, принимающий другой шаблон

#include <iostream>
#include <vector>
#include <list>
 
template <template <typename, typename> class ContainerType, typename T>
class Wrapper {
public:
    ContainerType<T, std::allocator<T>> container;
    
    void add(const T& value) {
        container.push_back(value);
    }
 
    void print() const {
        for (const auto& item : container) {
            std::cout << item << " ";
        }
        std::cout << std::endl;
    }
};
 
int main() {
    Wrapper<std::vector, int> vectorWrapper;
    vectorWrapper.add(1);
    vectorWrapper.add(2);
    vectorWrapper.add(3);
    vectorWrapper.print(); // Будет выведено: 1 2 3 
 
    Wrapper<std::list, int> listWrapper;
    listWrapper.add(4);
    listWrapper.add(5);
    listWrapper.add(6);
    listWrapper.print(); // Будет выведено: 4 5 6 
 
    return 0;
}

Пример 2: Шаблонная функция с параметром-шаблоном

#include <iostream>
#include <vector>
 
template <template <typename, typename> class Container, typename T>
void printContainer(const Container<T, std::allocator<T>>& container) {
    for (const auto& item : container) {
        std::cout << item << " ";
    }
    std::cout << std::endl;
}
 
int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    printContainer(vec); // Output: 1 2 3 4 5 
 
    return 0;
}