2016-09-21 97 views
10

我有一个模板函数,它接受可变数量的参数。既然你不能强制参数是某种类型,我想至少强制参数的数目不要高于编译时确定的数目(例如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

可以将参数限制为某种类型。你想对此做出答案吗?你是否要求参数完全是'T'还是可以转换为'T'的东西? – bolov

+0

@bolov是的,请,这将是非常有用的!我会+1 –

+1

我用这个创建了一个新帖子:http://stackoverflow.com/questions/39659127/restrict-variadic-template-arguments/39659128#39659128 – bolov

回答

20

为了使功能不可调用的时候有太多的参数,可以约束与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引用,因为它可以加速程序并且对非可复制类型更友好。

+3

这真的是一个有趣的方式使用SFINAE :) – Rakete1111

14

如果带有参数包的模板函数的参数数量超过编译时间确定值,编译器是否可以给出错误?

是,使用static_assert

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