Кратко
- Вариативные выражения облегчают выполнение одинаковых операций над всеми аргументами пакета параметров, упрощая и сокращая код.
- Вариативные индексы полезны для итерации и доступа к элементам пакета параметров, особенно при работе с кортежами и другими структурами данных.
- Вариативные базовые классы позволяют создавать классы с множественным наследованием, что делает код более гибким и универсальным.
Вариативные выражения (Variadic Expressions)
Вариативные выражения позволяют применять операторы к каждому элементу пакета параметров. Эти выражения часто используются для выполнения однородных операций над всеми аргументами пакета.
Пример 1: Суммирование аргументов
#include <iostream>
template<typename... Args>
auto sum(Args... args) {
return (args + ...); // Правосторонняя свертка
}
int main() {
std::cout << sum(1, 2, 3, 4, 5) << std::endl; // Output: 15
return 0;
}
Пример 2: Вывод аргументов
#include <iostream>
template<typename... Args>
void print(Args... args) {
(std::cout << ... << args) << std::endl; // Правосторонняя свертка
}
int main() {
print(1, 2, 3); // Output: 123
print("Hello, ", "world!"); // Output: Hello, world!
return 0;
}
Вариативные индексы (Variadic Indexes)
Вариативные индексы (variadic indexes) используются в шаблонах для обработки индексов параметров пакета. Это полезно для итерации и доступа к элементам пакета параметров.
Пример: Доступ к элементам std::tuple
#include <iostream>
#include <tuple>
#include <utility>
template<typename Tuple, std::size_t... Is>
void printTuple(const Tuple& t, std::index_sequence<Is...>) {
((std::cout << std::get<Is>(t) << " "), ...) << std::endl; // Правосторонняя свертка
}
template<typename... Args>
void printTuple(const std::tuple<Args...>& t) {
printTuple(t, std::index_sequence_for<Args...>{});
}
int main() {
auto t = std::make_tuple(1, 2.5, "example");
printTuple(t); // Output: 1 2.5 example
return 0;
}
Вариативные базовые классы (Variadic Base Classes)
С помощью вариативных шаблонов можно указать несколько базовых классов для одного класса. Это помогает создавать обобщенные классы с множественным наследованием.
Пример: Класс с множественным наследованием
#include <iostream>
template<typename... Bases>
class Derived : public Bases... {
public:
Derived(const Bases&... bases) : Bases(bases)... {}
void show() {
(Bases::show(), ...); // Правосторонняя свертка
}
};
class Base1 {
public:
void show() const {
std::cout << "Base1" << std::endl;
}
};
class Base2 {
public:
void show() const {
std::cout << "Base2" << std::endl;
}
};
int main() {
Derived<Base1, Base2> d(Base1(), Base2());
d.show(); // Output: Base1 Base2
return 0;
}