'忽略候选模板:无法推断模板参数' std::set

'Candidate template ignored: couldn't infer template argument' with std::set

我正在编写一个函数来使用它的迭代器来操作一个集合,但它给了我错误

candidate template ignored: couldn't infer template argument

最小可复现代码如下:

#include <bits/stdc++.h>
using namespace std;

template <typename T>
void foo(typename set<T>::iterator it1)
{
    // do something
}

int main() 
{
    set<int> aSet;
    foo(aSet.begin()); // no matching function call to 'foo'
}

我试过直接包含<set>,改变函数定义的顺序,但没有解决。最奇怪的是,我在其他函数中使用了 set 迭代器作为参数,而且它起作用了。 这些其他函数声明是这样的:

template <typename T>
void bar(set<T>& aSet, vector<T>& aVector, typename set<T>::iterator it);

(这些确切的参数,按照这个确切的顺序)。

foo 中,参数 typename set<T>::iterator 中的 Tnon-deduced contexts:

...the types, templates, and non-type values that are used to compose P do not participate in template argument deduction, but instead use the template arguments that were either deduced elsewhere or explicitly specified. If a template parameter is used only in non-deduced contexts and is not explicitly specified, template argument deduction fails.

T用在这个非推导的上下文中,在foo中没有明确指定它应该推导成什么类型​​,编译器不能推导类型;因此错误!

这意味着,如果您在 foo 中明确提及 T,它将按照引用中提到的进行编译。

foo<int>(aSet.begin()); // compiles!

或更好,提供迭代器作为模板参数

template <typename Iterator> 
void foo(Iterator it1)

如果您想限制 Iterator 仅用于 std::set<T>::iterator,您可以 SFINAE function. Here is an example code.

#include <type_traits> // std::enable_if, std::is_same
#include <iterator>    // std::iterator_traits

template<typename Iterator>
inline constexpr bool is_std_set_iterator = 
std::is_same_v<Iterator, typename std::set<typename std::iterator_traits<Iterator>::value_type>::iterator> ||
std::is_same_v<Iterator, typename std::set<typename std::iterator_traits<Iterator>::value_type>::const_iterator>;

template <typename Iterator>
auto foo(Iterator it1) -> std::enable_if_t<is_std_set_iterator<Iterator>, void>
{
    // do something
}

另一方面,在 bar 中,编译器已经将第一个函数参数推导为 std::set<int>& aSet 并看到 typename std::set<T>::iterator,它可以推导为 typename std::set<int>::iterator,因为 T 已经在前面的函数参数中推导为 int 。因此,它有效!


作为旁注,请参阅以下内容:

  • Why is "using namespace std;" considered bad practice?