Как в C++ создать функцию, принимающую переменное количество аргументов одного типа?

Как сделать метод/функцию, принимающую произвольное количество аргументов одного типа?
  • 10 февраля 2024 г. 20:29
Ответы на вопрос 2
В C++ для создания функции, принимающей переменное количество аргументов одного типа, можно использовать несколько подходов. Рассмотрим два основных: перегрузка функций с набором параметров и использование шаблонов с пакетами параметров (parameter packs) из стандарта C++11 и выше.

1. Использование `std::initializer_list`:
```cpp
#include <iostream>
#include <initializer_list>

void printNumbers(std::initializer_list<int> args) {
    for (auto number : args) {
        std::cout << number << ' ';
    }
    std::cout << std::endl;
}

int main() {
    printNumbers({1, 2, 3, 4, 5}); // выведет: 1 2 3 4 5
    return 0;
}
```

2. Использование шаблонных пакетов параметров (variadic templates) для функций с переменным числом аргументов:
```cpp
#include <iostream>

template<typename ...Args>
void printNumbers(Args... args) {
    // Распаковка пакета параметров с помощью списка инициализации
    (std::cout << ... << args) << std::endl;
}

int main() {
    printNumbers(1, 2, 3, 4, 5); // выведет: 12345
    return 0;
}
```

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

Обратите внимание, что в примере с вариативными шаблонами используется оператор распаковки `...`. Данный пример демонстрирует распаковку с использованием оператора сглаживания (fold expression), который доступен начиная с C++17. Если ваш стандарт языка старее C++17, то распаковку необходимо проводить другим способом, например, с использованием рекурсии или инициализации массива:

```cpp
#include <iostream>

template<typename T>
void printOne(const T& arg) {
    std::cout << arg << ' ';
}

template<typename ...Args>
void printNumbers(Args... args) {
    // Инициализация массива для вызова printOne для каждого аргумента
    int dummy[] = {0, (printOne(args), 0)...};
    static_cast<void>(dummy); // Предотвращаем предупреждения о неиспользуемой переменной
    std::cout << std::endl;
}

int main() {
    printNumbers(1, 2, 3, 4, 5); // выведет: 1 2 3 4 5
    return 0;
}
```

Здесь `printOne` - вспомогательная функция, которая обрабатывает один аргумент. Мы используем массив `dummy` для того, чтобы вызвать функцию для каждого элемента списка параметров. Обратите внимание, что создание этого массива - это трюк, позволяющий распаковать значение с помощью операции запятой. Сначала вызывается функция `printOne(args)`, а затем возвращается 0, чтобы инициализировать элемент массива.
На выбор: std::initializer_list , variadic arguments , variadic templates . 

Примеры по ссылкам есть. Последнее - вообще оверкилл, и в вашем случае вообще не нужно. Советую использовать initializer_list.
Похожие вопросы