为什么在这个模板模板参数中参数推导无法工作

4
我有以下的模板函数,它将模板模板参数作为其参数。
template<typename T, 
         template <typename... ELEM> class CONTAINER = std::vector>
void merge(typename CONTAINER<T>::iterator it )
{
   std::cout << *it << std::endl;
}

以下的代码使用了这段代码。

std::vector<int> vector1{1,2,3};
merge<int>(begin(vector1));

它按预期工作,但当我使用时出现问题
merge(begin(vector1));

它无法推断出T的类型。

我认为它可以从 std::vector<int>::iterator it; 推断出int作为类型。

为什么编译器不能推断类型?


建议:搜索“未推导上下文”。 - max66
这个问题大约3天前已经被问过(并得到了回答):https://stackoverflow.com/questions/56626007/specialize-a-template-class-using-a-nested-name-specifier-of-another-template-cl/。 - Radosław Cybulski
他正在尝试完全相同的事情 - 基于T :: iterator类型来推断类型T。这是不可能的,无论是在函数还是类中。 - Radosław Cybulski
1
请注意,您没有推断CONTAINER,而是使用默认值。 std :: set <int> set1 {1, 2, 3}; merge <int>(begin(set1)); [失败](http://coliru.stacked-crooked.com/a/8c7268a8bb01ed9b) - Caleth
如果你只需要从 decltype(it) 中获取 int,那么可以使用 std::iterator_traits<>::value_type。例如:template <typename Iterator, typename Value = std::iterator_traits<Iterator>::value_type> void merge(Iterator it) - Caleth
@RadosławCybulski 啊,抱歉,现在我明白了。虽然我认为不足以标记为重复,但它确实归结于相同的问题。 - 463035818_is_not_a_number
1个回答

6

我认为编译器可以从 std::vector<int>::iterator it; 推断出 int 类型。

为什么编译器不能推断类型?

不可以。

编译器不能:请查找“无法推导上下文”以获取更多信息。

并且期望进行推断不是合理的。

假设有一个如下的类:

template <typename T>
struct foo
 { using type = int; };

其中类型 type 总是 int,无论是什么类型的 T

假设有一个以下函数:

template <typename T>
void bar (typename foo<T>::type i)
 { }

接收一个int值(typename foo<T>::type始终为int)的函数。

从以下调用中应该推断出哪种T类型?

bar(0);

我认为在foo中使用“using type = T”。所以0是int,T也是int。编译器是否不可能实现? - user150497
@user150497,关键在于有无限多个T,使得foo<T>::typeint。该语言的定义是不需要在它们之间做出选择的。 - Caleth
1
@user150497 - 问题不在于它是不可能的。问题(在我看来)是它是不合理的。在您特定的情况下,内部类型允许推导模板参数。一般而言,这是不可能的,并且添加一个规则(无论如何都值得怀疑)以在特定情况下推导类型将迫使编译器进行大量的额外工作来查看所有可能的组合,并仅在单个模板匹配时接受代码。 - max66

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接