限制可变参数模板参数包中的参数数量

Limit the number of parameters in a variadic template parameter pack

我有一个模板函数,它接受可变数量的参数。由于您不能强制参数为某种类型,因此我至少希望强制参数的数量不超过编译时确定的数量(例如 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 包装函数中的所有参数提供一个通用容器。

Is it possible to make to compiler give an error if a template function with a parameter pack has the number of arguments higher than a compile-time determined value?

是,使用 static_assert:

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

为了让函数在参数过多时不可调用,可以用sfinae约束函数。这样,如果有另一个接受更多参数的重载,编译器将能够 select 正确的重载。

带有条件的简单 std::enable_if 就足够了:

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

为了可读性,您可以将约束放在函数的尾部 return 类型中:

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

这是使用 requires 和简洁模板语法的 C++20 更新版本:

auto setRequestArguments(const auto&... args) requires (sizeof...(args) <= 10) -> void {
    const std::vector<QGenericArgument> vec = {args... };
}