如何在函数签名中处理参数包?

时间:2014-02-27 08:03:06

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

使用参数包时,我觉得有点不舒服。我有一个功能

template <class ... Args>
void f( int x, Args ... args, int y )
{}

当然使用它就像这样有效:

f( 5, 3 );

我想知道为什么以下调用失败:

f( 5, 3.f, 3 );

这似乎是对我的直接使用参数包,但根据编译器Args未扩展。

当然,我可以轻松地将f替换为:

template <class ... Args>
void f( int x, Args ... args )
{
    static_assert( sizeof...( args ) >= 1, ... );
    extract y from args ...
}

问题:

  • 为什么我不能使用这样的参数包?似乎编译器可以轻松创建替换代码。或者上面的替换f()是否存在任何问题?

  • 如果参数的顺序对我很重要,那么处理此问题的最佳方法是什么? (考虑std::transform任意数量的输入迭代器。)

  • 为什么在上述情况下不禁止使用参数包?我认为,这是因为它们可以明确地扩展,例如, f<float>( 5, 3.f, 3 )

2 个答案:

答案 0 :(得分:2)

  

为什么我不能使用这样的参数包?似乎编译器可以轻松创建替换代码。或者上面替换f()有什么问题吗?

在这种特殊情况下可能很容易,也可能不在其他情况下。真正的答案是标准指定了行为,标准没有指定任何转换......通常很少。

我会注意到您的转换不适用于SFINAE ,因为static_assert是硬错误,因此我很高兴转换未执行。 (提示:如果使用f的单参数版本重载了float会怎样?f(1)会选择是否进行转换?) < / p>

  

如果参数的顺序对我来说真的很重要,最好的方法是什么? (考虑std::transform任意数量的输入迭代器。)

明确指定模板包参数。

  

为什么在上述情况下不禁止使用参数包?我认为,这是因为它们可以明确地扩展,例如, f(5,3.f,3)?

我认为你的假设是正确的;如果明确指定,则按预期工作。

答案 1 :(得分:1)

您可以使用其他非可变参数模板参数,但只有在将这些非可变参数分配给非可变参数后,剩余部分才能构成可变参数的参数包。因此,您必须将参数列表末尾的int y移动到可变参数之前。类似的东西:

template <class... Args>
void f(int x, int y, Args... args)
{}