Ограничьте количество параметров в пакете параметров вариационного шаблона

У меня есть функция шаблона, которая принимает переменное количество аргументов. Поскольку вы не можете заставить аргументы быть определенного типа, я хотел бы, по крайней мере, заставить число аргументов не быть выше, чем определенное количество времени компиляции (например, 10).

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

template <class ...Args>
void setRequestArguments(const Args&... args)
{
    const std::vector<QGenericArgument> vec = { args... };
    qDebug() << sizeof...(args);
    // Do stuff...
    // for (unsigned i = 0; i < vec.size(); ++i) {
    //     qDebug() << vec[i].name();
    // }
}

Я хочу использовать его для универсального контейнера для всех аргументов в QMetaObject::invokeMethod обертке.

Ответ 1

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

Простой std::enable_if с условием будет достаточно:

template <class ...Args, std::enable_if_t<(sizeof...(Args) <= 10)>* = nullptr>
void setRequestArguments(Args&&... args)
{
    const std::vector<QGenericArgument> vec = { std::forward<Args>(args)... };
}

Для удобства чтения вы можете поместить ограничение в возвращаемый тип возвращаемой функции:

template <class ...Args>
auto setRequestArguments(Args&&... args) -> std::enable_if_t<(sizeof...(args) <= 10)>
{
    const std::vector<QGenericArgument> vec = { std::forward<Args>(args)... };
}

РЕДАКТИРОВАТЬ: Я добавил ссылку на отправку вместо ссылки на константу, поскольку она может ускорить работу программы и более дружелюбна к нескольким типам.

Ответ 2

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

Да, используйте static_assert:

template <class ...Args>
void setRequestArguments(const Args&... args)
{
    static_assert(sizeof...(args) <= 10, "You can't have more than 10 arguments!");
    //Stuff...
}