Функция с переменным числом аргументов с известными типами, путь С++ 11

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

Но в обеих вышеупомянутых схемах мы не знаем (и не можем форсировать) типы аргументов во время компиляции afaik. Я ищу, чтобы передать переменные аргументы известных типов для функции. Я думаю, что это можно сделать, потому что я читал об этом здесь:

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

Возможно ли это? Если да, как я могу это сделать?

Ответ 1

Прямо писать функцию с вариационными шаблонами, которые принимают произвольное количество аргументов. Единственное отличие от общего шаблона состоит в том, что конкретный тип используется в качестве первого аргумента (head) - вместо параметра шаблона. В следующем примере показана функция foobar, которая принимает произвольное количество строк.

// used for end of recursion - and for the empty arguments list
void foobar() { }

template <typename ...Tail>
void foobar(const std::string& head, Tail&&... tail)
{
    // do something with head
    std::cout << head << '\n';
    // call foobar recursively with remaining arguments
    foobar(std::forward<Tail>(tail)...);
}

foobar("Hello", "World", "...");

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

void foobar(std::initializer_list<std::string> values)
{
    for (auto& value : values) {
        // do something with value
        std::cout << value << '\n';
    }
}

foobar({ "Hello", "World", "...", });

К сожалению, дополнительные фигурные скобки требуются при использовании std::initializer_list с регулярными функциями. Они не требуются для конструкторов, если используется новый синтаксис инициализатора.

Изменить: Переписал ответ в соответствии с отзывами. В частности, я изменил порядок двух решений/примеров.

Ответ 2

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