3

例如,参考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;
}
4

1 回答 1

5

您在评论中提出的建议 - 让函数接受另一个模板参数 - 不会按您的预期工作。这是您建议的代码:

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不能从参数类型中推断出来(InputIteratorT类型可以从两个参数中推断出来,但仅从签名中就没有上下文),所以这个调用会因为编译器错误而失败。这里的使用std::iterator_traits是一种通用模板模式,用于从迭代器类型本身中提取有关迭代器的信息。

于 2016-11-21T16:34:28.793 回答