Traits技术可以用来获得一个 类型 的相关信息,假如下面是一个迭代器类,T表示迭代器指向的类型。
template <typename T>
class myIterator
{
};
当使用myIterator时,怎么才能知道其指向元素的类型,我们可以在这个类添加一个内嵌类型,如下:
template <typename T>
class myIterator
{
...
};
这样当我们使用myIterator类型时候,就可以通过myIterator::value_type来知道myIterator所指向的类型。
现在我们来设计一个算法,使用这个信息。
template <typename T>
typename myIterator<T>::value_type Foo(myIterator<T> i)
{
...
}
这里我们定义一个foo函数,返回值为参数i所指向的类型,也就是T,为什么我们要兴师动众的使用value_type,因为当我们修改foo函数时,使他能够适应所有的迭代器类型,我们还可以这样写:
template <typename I>////这里的I可以是任意类型的迭代器
typename I::value_type Foo(I i)
{
...
}
现在定义任何内嵌类型迭代器,都可以作为Foo参数,并且Foo返回值类型和迭代器所指元素类型一致,到现在貌似一切问题都已解决,我们并没有使用任何新的技术,但考虑下面的问题,新的问题便显现出来了。
原生指针也可以做为迭代器使用,然而我们没办法为原生指针添加一个value_type的内嵌类型,如此一来我们的Foo函数就不能用原生指针了,这不能不说是一大缺憾,那有什么办法解决吗?有,那就是我们的类型信息榨取机Traits登场:
我们可以不使用myIterator里面的value_type,而是直接通过另一个类来把这个信息读取出来:
template <typename T>
class Traits
{
};
这样我们就可以通过 Traits<myIterator>::value_type来获得myIterator的value_type类型,于是可以可以把函数这样写
template <typename I>//这里的I可以是任意类型的迭代器
typename Traits<I>::value_type Foo(I i)
{
...
}
即时这样,原生指针的问题还是没有解决,因为Traits类也没办法获得原生指针相关的信息,于是我们又拿出C++的又一利器,编特化(partial specialization)
template <typename T>
Class
{
typedef typename T
};
通过上面我们知道一个事实,T*类型指针指向的元素的类型为T,
如此一来我们就可以使用原生指针如下:
int *p;
int i = Foo(p);
Traits会自动推导出p所指向的类型为int;从而foo正确返回