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

时间:2016-09-21 15:47:33

标签: c++ templates c++11 variadic-templates variadic-functions

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

2 个答案:

答案 0 :(得分:21)

要在参数太多时使函数不可调用,可以使用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)... };
}

编辑:我添加了转发引用而不是const引用,因为它可以加快程序速度,对非可复制类型更友好。

答案 1 :(得分:15)

  

如果带参数包的模板函数的参数个数高于编译时确定的值,是否可以使编译器发出错误?

是的,请使用static_assert

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