在写作泛型函数或代码时,我们可能存在这样的需要:与参数相关的其它类型,比如一个迭代器的值的类型。
本文要向大家展示一个函数模板推导机制使用技法,这个在STL的许多排序算法中广泛使用,当然大家也可能在不小心地使用,这此把它点破,以让大家可以更有意识地去使用这个在大师那里已经轻车熟路的技法。
考虑一个情况,我们在写一个泛型函数,它接受一对迭代器,要做的事就是对这一对迭代器之间的元素进行排序,其中将出现这幕:我需要对两个值进行交换。不知道大家有没有写过这样的代码,现在的问题是如何实现这两个值的交换?如:
{
//交换两个迭代器指向的值
//注意此时我们并不(*itr)的类型
}
请大家离开电脑屏幕,自己想想如何实现这中间的一段代码?其实这段代码很简单,只要使用std::swap就可以实现了,但是如果不使用std::swap又如何呢?你有什么办法吗?可能需要这么做
*itr=*(itr+1)
*(itr+1)=*itr;
对,大家想的很正确,但问题就在于我们不知道如何写那个可爱的“Type”。此时你没有办法,可以说如果C++没有typeof的话,在此谁也没有办法。但大家又回想起来了,为什么简单地使用std::swap就可以了,上面的代码可以简单地写作:
{
std::swap(*itr, *(itr+1));
}
上述的代码的玄机就在函数模板的参数推导机制,我们看看std::swap典型的实现方法:
void swap(T& l, T& r)
{
T> l=r;
> }
大家注意了,此时swap是一个函数模板,当我们调用的时候,编译器会根据参数的类型生成一个特定的swap版本,无论是itr指向是什么类型值,编译器总是可以我们解决这个难题的。通过swap,我们实现隐匿提取了*itr的类型。这个技法在STL与boost库的实现大量存在,因为它们其中的算法大多是使用迭代器的,而此时可能需要迭代器指向的值的类型。当然STL与boost中还存在其它替代方法,其中iterator_traits就是一个方案,但是它一个人为的惯用法,一个重要的经验,可是不如此处自动化机制优雅。
swap函数只是提取迭代器值的类型,相同的方法可以提取多种相关数据类型。当然使用要小心,要避免把自己代入一个人为的优雅之中,所谓人为的优雅就是指通过一个看似优雅的方法去做完一件事,可是之后却发现这个优雅完全是画蛇添足。
祝大家学习愉快!
转载自:http://www.easycpp.org/book/c%E7%BC%96%E7%A8%8B%E6%8A%80%E6%B3%95/%E5%87%BD%E6%95%