为泛型函数定义自定义迭代器特征

Defining a custom iterator traits for a generic function

本文关键字:迭代器 特征 自定义 定义 泛型 函数      更新时间:2023-10-16

我正试图编写一个泛型函数,该函数将根据它给出的迭代器在编译时派生返回类型。通常这是通过std::iterator_traits完成的,但是我也想定义我自己版本的iterator_traits,称为my_iterator traits。下面是我的代码:

#include <cassert>
#include <iterator>
#include <vector>
using namespace std;
template <typename I>
struct my_iterator_traits {
    typedef typename I::value_type                     value_type;
    typedef typename I::iterator_category       iterator_category;
};
template <typename T>
struct my_iterator_traits<T*> {
    typedef T                                         value_type;
    typedef std::random_access_iterator_tag    iterator_category;
};                                                               
template <typename II>
typename my_iterator_traits<II>::value_type f(II b, II e) {
    typename my_iterator_traits<II>::value_type val = 0;
    return val;
}
int main () {
    int a[] = {2, 3, 4};
    int i = f(a, a + 3);
    assert(i == 0);
    // vector<int> v = {2};
    // f(v.begin(), v.end());
    // assert(j == 0);
    return 0;
}

直到并包括main函数和f()函数的所有内容都是完全有意义的。在main中,我创建了一个int数组,对其调用f(),并确认我得到的输出是一个值为0的int。

不清楚的是:我有两个模板,上面跟着struct关键字。使用第二个(将T*作为模板参数的那个)是完全有意义的。具体来说,为什么我们需要第一个结构模板(没有模板参数的那个)?更重要的是,这两个结构模板之间的关系是什么?

第一个是模板的声明,第二个是第一个的部分特化。像链接中解释的部分专门化可以自定义模板参数(例如:一些固定的参数,对你引用的参数的一些限制(指针,引用等),等等…)。

第一个template<typename>structtemplate,第二个是第一个template的专门化。

template专门化类似于基于模式匹配的覆盖(但不是真的)。如果template的参数可以通过专门化模式匹配,则使用它。

这个模式匹配不像函数重写那样进行类型转换。然而,SFINAE正在发挥作用,用于高级工作。