"候选模板被忽略:无法推断模板参数"与 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>,更改函数定义的顺序,但没有任何解决方法。最奇怪的是,我在其他函数中使用了设置迭代器作为参数,并且它起作用了。 这些其他函数声明如下所示:

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

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

foo中,参数typename set<T>::iterator中的T是一个非推导的上下文

。用于组成P的类型、模板和非类型值不参与模板参数推导,而是使用在其他地方推导或显式指定的模板参数。如果模板参数仅在非推导上下文中使用,并且未显式指定,则模板参数推导失败

T用于这种非推导上下文中,并且没有明确指定foo它应该推导的类型,编译器无法对类型进行推断;因此错误!

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

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

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

template <typename Iterator> 
void foo(Iterator it1)

如果只想限制std::set<T>::iteratorIterator,则可以使用SFINAE功能。下面是一个示例代码。

#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<int>::iteratortypename std::set<T>::iterator,因为T在前面的函数参数中已经推导出为int。因此,它有效!


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

  • 为什么我不应该 #include ?
  • 为什么是"使用命名空间 std;"被认为是不良做法?

相关内容

  • 没有找到相关文章

最新更新