c++ - 为什么在模板函数中使用 iterator_traits 而不是仅仅使用另一个模板类型参数?

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

关于c++ - 为什么在模板函数中使用 iterator_traits 而不是仅仅使用另一个模板类型参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40724465/

相关文章:

c++ - '_start'的多重定义

c++ - 为什么将函数传递给内核会导致数据变得不可变?

c++ - 具有模板模板参数的模板定义,可以专门化为类,例如,std::vector<std::string> 或 std::map<std::tree>

c++ - 这种意外的 std::vector 行为是什么?

c++ - 更改成员变量顺序时出现堆损坏

c++ - 使用另一个类的静态成员函数时构造函数中的未解析静态符号。

c++ - Constexpr变量不是编译时值吗?

c++ - 禁止模板虚函数是一种不必要的谨慎吗?

c++ - std::make_unsigned 没有给出预期的结果

c++ - 如何用非平凡的初始值填充 vector ?