有问题的主要问题是我想编写一个接受两个可变长度参数集的函数。
我决定去的抽象是模仿以下调用语法:
f({a,b,c},x,y);
如果a
,b
和c
都具有相同的类型,则可以使其与之一起使用
template <typename X, typename... A>
void f(std::initializer_list<X> xs, A&&... as) { . . . }
但是使用std::tuple
而不是std::initializer_list
的相似函数定义不允许我使用所需的语法。
template <typename... X, typename... A>
void f(const std::tuple<X...>& xs, A&&... as) { . . . }
我可以使用一些技巧来允许第一组中的类型是异构的吗?
附录:通常,我不知道X...
的大小。
附录2:有人知道在std::tuple t{a,b,c}
中使用括号初始化程序的技术原因,但在模板参数上下文中不知道吗?是因为在我的示例中xs
没有被X...
扩展?
不,目前无法使用所需的语法。初始化列表只能推导为均一类型的数组或std::initializer_list
。
这是一个特殊规则。初始化列表没有类型,根本无法推导为其他任何类型。如果函数参数不是数组或std::initializer_list
,则为其指定了初始化程序列表的参数将成为非推论上下文,并且模板参数推导将忽略它。
特别是类模板参数的推导不能在函数参数中确定,以从支撑初始化列表中确定类型,因为自C ++ 17起可以在变量定义中完成。此类功能未添加到语言中。
原则上,您可以使用例如一个std::variant
数组作为参数,但是只能在运行时解析为该类型,并且不太可能是您想要的。
您需要在初始化程序列表花括号中添加类型名称或函数调用,如
f(std::forward_as_tuple(a, b, c), x, y)
或者您也可以使用标签类型来指示平面参数列表中第一个包的结尾:
f(a, b, c, tag, x, y)
然后可以通过一些模板工作来检测标签。