Variadic模板参数顺序,它们必须始终是最正确的参数吗?

kbi*_*irk 15 c++ templates variadic-templates c++11

我想修改现有的类构造函数:

template< typename T, typename... Ts >
MyClass( std::vector<T>& head, Ts& ...tail );
Run Code Online (Sandbox Code Playgroud)

这样就可以指定处理标志:

template< typename T, typename... Ts >
MyClass( MyEnum myEnum, std::vector<T>& head, Ts& ...tail );
Run Code Online (Sandbox Code Playgroud)

这工作正常,但是我想知道是否有一种方法可以将它指定为最右边的参数,并且可能具有默认值.我从来没有见过像这样声明的变量模板,但是再一次,我找不到任何明确说明它们不可能的东西.我试过了:

template< typename T, typename... Ts >
MyClass( std::vector<T>& head, Ts& ...tail, MyEnum myEnum );

...

MyClass myClass( dataA, dataB, dataC, MyEnum::VALUE );
Run Code Online (Sandbox Code Playgroud)

但编译器不喜欢它,我假设它是由于可变参数模板如何解析而且它们必须是最右边的参数?

这在C++ 11中是否可行?

T.C*_*.C. 20

在中间使用函数参数包并不违法,但是当你尝试使用构造函数执行此操作时会遇到一个巨大的障碍:在参数声明列表的末尾没有出现的函数参数包是非推导上下文(§14.8.2.5[temp.deduct.type]/p5,最后一个项目符号点),并且必须使用模板参数推导调用构造函数模板 - 您无法显式指定其模板参数.

也就是说,要在中间放置一个函数参数包,您必须在调用函数时显式指定模板参数:

template< typename T, typename... Ts >
void test( const std::vector<T>& head, const Ts& ...tail, MyEnum myEnum ) { }

test<double, int>(std::vector<double>(), 10, MyEnum()); // legal
Run Code Online (Sandbox Code Playgroud)

但这不会编译:

test(std::vector<double>(), 10, MyEnum()); // No deduction performed for the parameter pack
Run Code Online (Sandbox Code Playgroud)

但是,在调用构造函数模板时,语言中没有办法明确指定模板参数(§14.8.1[temp.arg.explicit]/p7):

[ 注意:因为显式模板参数列表遵循函数模板名称,并且因为在不使用函数名称的情况下调用转换成员函数模板和构造函数成员函数模板,所以无法为这些函数模板提供显式模板参数列表.- 结束说明 ]

因此,对于构造函数,您必须依赖模板参数推导 - 如果函数参数包不在最后,则不起作用.


Mar*_*cia 9

您可以在以下内容中"包装"可变参数std::tuple:

template< typename T, typename... Ts >
MyClass( std::vector<T>& head, std::tuple<Ts& ...> tail, MyEnum myEnum );

...

MyClass myClass( dataA, std::tie( dataB, dataC ), MyEnum::VALUE );
// NOTE:                ^^^^^^^^^              ^
Run Code Online (Sandbox Code Playgroud)

实例(转2)