继续理解traits技术。
当我们处理原生指针时,会遇到需要知道其所指对象类型这样的问题。如何实现呢?
template <class T>
void testTypeForward(T t)
{
// write code here
}
C++中我们不允许使用typedef(*T)这样的语句。
其中的一种解决方案是:将这个功能实现传递给另一个函数去完成。
template <class T1, class T2>
void typeForwardHelper(T1 t1, T2 t2)
{
T2 type;
// write code here
}
// 基于模板的类型推导
template <class T>
void testTypeForward(T t)
{
typeForwardHelper(t, *t);
}
上面这个思路的使用很受限,仅仅只能在参数传递其作用,万一我们还需要作为返回值。
很遗憾 下面的这段代码编译会报错。
template <class T1, class T2>
T2 typeForwardHelper(T1 t1, T2 t2)
{
T2 type;
// write code here
return type;
}
// 基于模板的类型推导
template <class T>
(*T) testTypeForward(T t)
{
return typeForwardHelper(t, *t);
}
其实我们可以考虑用迭代器,在其内部定义一个指向对象类型的别名,比如类似下面这样:
template <class T>
struct MyIter
{
typedef T value_type;
T* ptr;
};
template <class I>
typename I::value_type testTypeForward(I iter)
{
return *iter;
}
但是,这个并不能解决原生指针的问题,对于原生指针编译仍然会报错!!!(原生指针并没有value_type这个属性,对不对?)
恩,这时候要用到模板的偏特化(上一篇介绍过相关的概念)。
template <class I>
struct iterator_traits
{
typedef I::value_type value_type;
}
template <class T>
struct iterator_traits<T*>
{
typedef T value_type;
};
template <class T>
struct iterator_traits<const T*>
{
typedef T value_type;
};
template <class I>
typename iterator_traits<I>::value_type testTypeForward(I iter)
{
return *iter;
}
注意我们为T*和const T*都实现了偏特化版本。
上面这个过程就是类型萃取,其目的在于将迭代器类型用于定义变量、函数返回等操作。