为什么在模板函数中使用 iterator_traits 而不是只使用另一个模板类型参数?
Why use iterator_traits in a template function instead of just using another template type argument?
例如,参考 cplusplus.com 中的这个片段:
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const T& val)
{
typename iterator_traits<InputIterator>::difference_type ret = 0;
while (first!=last) {
if (*first == val)
++ret;
++first;
}
return ret;
}
问题是为什么在此上下文中使用 iterator_traits
而不是采用另一个模板参数,如下所示:
template <class InputIterator, class T, class DiffType>
DiffType count(InputIterator first, InputIterator last, const T& val)
{
DiffType ret = 0;
while (first!=last) {
if (*first == val)
++ret;
++first;
}
return ret;
}
您在评论中提出的建议 - 让函数接受另一个模板参数 - 不会像您预期的那样工作。这是您建议的代码:
template <class InputIterator, class T, typename DiffType>
DiffType count(InputIterator first, InputIterator last, const T& val)
{
DiffType ret = 0;
while (first!=last) {
if (*first == val)
++ret;
++first;
}
return ret;
}
此代码的问题在于不再编译:
std::vector<int> v = /* ... */;
auto numElems = count(v.begin(), v.end(), 137); // <--- Error!
这里的问题是,为了调用函数模板,每个模板参数要么必须从参数类型中推导出来,要么由调用者明确指定。在这里,类型 DiffType
不能从参数类型中推断出来(InputIterator
和 T
类型可以从两个参数中推断出来,但仅从签名中没有上下文),所以这个调用会因编译器错误而失败。这里使用 std::iterator_traits
是一种通用模板模式,用于从迭代器类型本身提取有关迭代器的信息。
例如,参考 cplusplus.com 中的这个片段:
template <class InputIterator, class T>
typename iterator_traits<InputIterator>::difference_type
count(InputIterator first, InputIterator last, const T& val)
{
typename iterator_traits<InputIterator>::difference_type ret = 0;
while (first!=last) {
if (*first == val)
++ret;
++first;
}
return ret;
}
问题是为什么在此上下文中使用 iterator_traits
而不是采用另一个模板参数,如下所示:
template <class InputIterator, class T, class DiffType>
DiffType count(InputIterator first, InputIterator last, const T& val)
{
DiffType ret = 0;
while (first!=last) {
if (*first == val)
++ret;
++first;
}
return ret;
}
您在评论中提出的建议 - 让函数接受另一个模板参数 - 不会像您预期的那样工作。这是您建议的代码:
template <class InputIterator, class T, typename DiffType>
DiffType count(InputIterator first, InputIterator last, const T& val)
{
DiffType ret = 0;
while (first!=last) {
if (*first == val)
++ret;
++first;
}
return ret;
}
此代码的问题在于不再编译:
std::vector<int> v = /* ... */;
auto numElems = count(v.begin(), v.end(), 137); // <--- Error!
这里的问题是,为了调用函数模板,每个模板参数要么必须从参数类型中推导出来,要么由调用者明确指定。在这里,类型 DiffType
不能从参数类型中推断出来(InputIterator
和 T
类型可以从两个参数中推断出来,但仅从签名中没有上下文),所以这个调用会因编译器错误而失败。这里使用 std::iterator_traits
是一种通用模板模式,用于从迭代器类型本身提取有关迭代器的信息。