'忽略候选模板:无法推断模板参数' 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
中的 T
是 non-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?
我正在编写一个函数来使用它的迭代器来操作一个集合,但它给了我错误
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
中的 T
是 non-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?