可变参数模板参数包推导失败

问题描述 投票:1回答:1

我正在尝试元编程。当我尝试将variadic typesstd::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
} 

see online

我直观地期望这两个函数都能编译而不会出错,但是似乎编译器对此有所抱怨。

[有人可以解释为什么f给出扣除/替代错误,但f2没有吗?

是否有解决方法(我确定有)?

编译器:x86-x64 GCC 9.2-std = c ++ 17选项

c++ variadic-templates template-argument-deduction
1个回答
0
投票

f失败,因为编译器无法确定您传递给它的元组参数tArgs&&...列表的一部分还是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);
}
© www.soinside.com 2019 - 2024. All rights reserved.