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

Mar*_*ayr 6 c++ variadic-templates c++11

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

template <class ... Args>
void f( int x, Args ... args, int y )
{}
Run Code Online (Sandbox Code Playgroud)

当然使用它像这样工作:

f( 5, 3 );
Run Code Online (Sandbox Code Playgroud)

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

f( 5, 3.f, 3 );
Run Code Online (Sandbox Code Playgroud)

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

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

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

问题:

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

  • 如果参数的顺序对我来说真的很重要,那么解决这个问题的最佳方法是什么?(想想std::transform任意数量的输入迭代器.)

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

Mat*_* M. 2

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

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

我会注意到您的转换不适用于 SFINAE,因为static_assert这是硬错误,所以我很高兴没有执行转换。(提示:如果f使用带 a 的单参数版本重载float,会选择带/不带转换的f(1)?)

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

显式指定模板包参数。

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

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