我试图编写一个泛型函数,它将根据给定的迭代器在编译时派生一个返回类型。通常这是通过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()
,并确认我得到的输出是一个值为零的int。
以下内容并不清楚。我在顶部有两个模板,后跟struct
关键字。使用第二个(以T*
作为模板参数的那个)是完全合理的。具体来说,为什么我们需要第一个结构模板(没有模板参数的模板)?更重要的是,两个结构模板之间的关系是什么?
答案 0 :(得分:0)
第一个是模板的声明,第二个是第一个的partial specialization。如链接中所解释的部分特化可以定制模板参数(例如:一些固定参数,对您所引用的参数(指针,引用等等)的某些限制等)。
答案 1 :(得分:0)
第一个template<typename>struct
是template
,第二个是第一个template
的特化。
template
特化与类似于覆盖(但不是真的)类似于基于模式匹配的东西。如果template
的参数可以通过专门化模式进行匹配,则可以使用它。
此模式匹配不会以与函数覆盖相同的方式进行类型转换。然而,SFINAE正在进行高级工作。