我正在尝试元编程。当我尝试将variadic types
与std::tuple
并置时,我遇到了一个问题。
#include <tuple>
template<typename... Args , typename... TupleArgs>
void f( Args&&... , const std::tuple<TupleArgs...>& )
{ }
template<typename... Args , typename... TupleArgs>
void f2( const std::tuple<TupleArgs...>& , Args&&... )
{ }
int main(){
auto t = std::make_tuple( 1 , 2 , 2.0 , 3.0f );
// f ( 1 , 2 , t ); // deduction/substition failed
f2( t , 1 , 2 ); // Ok, no problem
}
我直观地期望这两个函数都能编译而不会出错,但是似乎编译器对此有所抱怨。
[有人可以解释为什么f
给出扣除/替代错误,但f2
没有吗?
是否有解决方法(我确定有)?
编译器:x86-x64 GCC 9.2和-std = c ++ 17选项
f
失败,因为编译器无法确定您传递给它的元组参数t
是Args&&...
列表的一部分还是const std::tuple<TupleArgs...>&
实例(在这种情况下是一个单元组,碰巧是可变参数类型)。
f2
的第一个参数实际上是单个类型(元组),后跟可变参数包Args&&...
,因此您在第一个参数之后传递的任何参数显然都属于Args&&...
。请注意,我指的是实际函数的参数,而不是模板声明。函数原型是导致此行为的原因。
如果要在函数参数列表中包含两个参数包,则可以执行一些技巧,例如将BOTH放入元组,或将一个放入模板模板参数(嵌套模板)。
我提供了两个示例解决方案。我将f
更改为使用两个元组,并创建了一个使用模板template参数的新函数f3
。
#include <tuple>
template<typename... Args, typename... TupleArgs>
void f(const std::tuple<Args...>&, const std::tuple<TupleArgs...>&)
{ }
template<typename... TArgs, template <typename...> class T, typename... TupleArgs>
void f3(T<TArgs...>&, const std::tuple<TupleArgs...>&)
{ }
template<typename... Args, typename... TupleArgs>
void f2(const std::tuple<TupleArgs...>&, Args&&...)
{ }
int main() {
auto t = std::make_tuple(1, 2, 2.0, 3.0f);
auto t2 = std::make_tuple(1, 2);
f( t2 , t ); // FIXED
f2(t, 1, 2); // Ok, no problem
f3(t2, t);
}