Не определяйте вариадические функции в стиле С

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

В С++11 возможно использовать вариадические шаблонные функции и пачки параметров.

Неправильно:

#include <cstdarg>

int add(int first, int second, ...) {
    int r = first + second;
    va_list va;
    va_start(va, second);
    while (int v = va_arg(va, int)) {
        r += v;
    }
    va_end(va);
    return r;
}

Правильно (С++17):

#include <type_traits>

template <typename Arg, typename... Ts, typename std::enable_if_t<std::is_integral_v<Arg>, int>
int add(Arg f, Ts... rest) {
    if constexpr (sizeof...(rest) == 0)
        return f;
    else
        return f + add(rest...);
}

или:

#include <type_traits>

template <typename Arg, typename... Ts, typename std::enable_if_t<std::is_integral_v<Arg>, int>
int add(Arg i, Arg j, Ts... all) {
    return i + j + (... + all);  // fold expression для rest
}