2015-12-29 26 views
0

我试图使用一些可变参数模板参数,但我很快被我没有设法理解的错误所阻止。C++多变量模板不绑定到函数参数

#include <tuple> 

template <typename T> 
struct Foo 
{ 
    typedef T type; 
}; 

// return a tuple of pair of args and Foo templated on Types 
template <typename Head, typename ...Args, typename Type, typename ...Types> 
auto func(Head arg, Args... args) 
{ 
    return std::tuple_cat(std::make_tuple(std::make_pair(arg, Foo<Type>())), 
         func<Args..., Types...>(args...)); 
} 

template <typename Head, typename Type> 
auto func(Head arg) 
{ 
    return std::make_tuple(std::make_pair(arg, Foo<Type>())); 
} 

int main() 
{ 
    func<int, bool, char>(1, 2, 3); 
} 

这里FUNC试图解开模板参数,使一对FUNC论证的元组和一个Foo结构模板在第二可变参数模板,但我有:

test.cc:25:3: error: no matching function for call to 'func' 
func<int, bool, char>(1, 2, 3); 
^~~~~~~~~~~~~~~~~~~~~ 
test.cc:11:6: note: candidate template ignored: couldn't infer template argument 'Type' 
auto func(Head arg, Args... args) 
^ 
test.cc:18:6: note: candidate function template not viable: requires single argument 'arg', but 3 
    arguments were provided 
auto func(Head arg) 
^ 
1 error generated. 

为什么类型不能为推断 ? (海湾合作委员会告诉我一样)

我确信在sed :: tuple_cat实现(https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.5/a01066_source.html)之后可以使用多个可变参数模板,我认为这是一个简单的例子,如果有解决方案,或者如果标准不接受这一点。

感谢您的帮助,

+1

它应该推断为什么?你告诉它'Head'和2'Args',并给出了它们各自的函数参数。 'Type'不在那里使用,所以它不可能被推断出来。 – chris

回答

2

推导出最后一个参数。

...模板参数是贪婪的 - 它们将消耗传递参数并且不会为以后的模板参数“保存”任何参数。

一旦完成,扣除发生从非模板函数参数。

交换这样的:

template <typename Type, typename ...Types, typename Head, typename ...Args> 
auto func(Head arg, Args... args) 

而且,摆脱对方超负荷,所以func<int,int>(3)一点也不含糊。

这使得递归突破,但很容易解决:

template <class... Types, class... Args> 
auto func(Args... args) 
{ 
    return std::make_tuple(std::make_pair(args, Foo<Types>())...); 
} 

其中有是很好的和短的奖金。

+0

其实我只需要在1个类型上模板Foo,所以第二个版本不起作用。 而第一个仍然ambigous。它似乎不想解压缩...参数 – yayg

+0

@yayg我只在第二个示例中一次性传递'Foo' ...包扩展对表达式起作用。 – Yakk

+0

非常感谢!我不知道这个真棒功能:D – yayg

0

的关键数据这里的一点是,可变参数的参数将一个空的列表相匹配。这有几个后果。

第一个后果是,给下面的模板声明:

template <typename Head, typename ...Args, typename Type, typename ...Types> 

及以下实例:

<int, bool, char> 

有几种方法的实例可以匹配模板:

1 。

Head   int 
...Args  bool 
Type   char 
... Types  (empty list) 

2.

Head   int 
...Args  (empty list) 
Type   bool 
... Types  char 

所以,这就是不确定性的来源之一。 main()中的参考可以匹配模板定义。尽管在某些情况下可以解决这种模糊问题有各种神秘规则,但总是最好不要依赖神秘的模板消歧规则,或者至少不要再使用几种标准的基本方法。

但是,回到主题上,编译器将在这里落后八球,但没有明确的候选人来解决main()中的模板引用。但情况变得更糟。鉴于

auto func(Head arg, Args... args) 

auto func(Head arg) 

因为,再一次,一个variatic参数,在这种情况下,它Args...,可以匹配空列表,然后,例如:

func(4) 

能匹配任一功能签名。

将所有这些因素结合在一起,编译器无法在这里真正做出正面或反面。