traits编程技巧

最近在学习《STL源码剖析》,对书中介绍的traits很有感。

搜到的前辈的博客,这篇博文写的很好,感谢。

自己在写一下,加深自己的理解。


举例:加入我们现在有一个算法,可以对传入的迭代器前进N步。

template <typename ITERATOR>
void move_n_step(ITERATOR &itor, int n)
{
  for (int i = 0; i < n; i++)
    itor++;
}
代码很了然,然后我们有两个迭代器,分别是链表迭代器和数组迭代器。

class list_itor
{
  public:
    void operator++(int)
    {
      std::cout << "list_iter: " << __func__ << std::endl;
    }
};

class array_itor
{
  public:
    void operator++(int)
    {
      std::cout << "array_iter: " << __func__ << std::endl;
    }
};
为了方便期间,这两个迭代器只实现了后置++操作。

下面是第一版程序:

#include <iostream>

template <typename ITERATOR>
void move_n_step(ITERATOR &itor, int n)
{
  for (int i = 0; i < n; i++)
    itor++;
}

class list_itor
{
  public:
    void operator++(int)
    {
      std::cout << "list_iter: " << __func__ << std::endl;
    }
};

class array_itor
{
  public:
    void operator++(int)
    {
      std::cout << "array_iter: " << __func__ << std::endl;
    }
};

int main()
{
  list_itor li;
  array_itor ai;
  move_n_step(li, 2);
  move_n_step(ai, 3);
  return 0;
}


但是,我们发现,对于数组性迭代器,我们也是采用++的方式前进,而数组型迭代器是支持算数运算的。

所以我们实现了2个算法,一个处理链表迭代器,一个处理数组迭代器。

#include <iostream>

template <typename ITERATOR>
void move_n_step_list(ITERATOR &itor, int n)
{
	for (int i = 0; i < n; i++)
		itor++;
}

template <typename ITERATOR>
void move_n_step_array(ITERATOR &itor, int n)
{
	itor.operator+(n);
}

class list_itor
{
	public:
		void operator++(int)
		{
			std::cout << "list_itor: " << __func__ << std::endl;
		}
};

class array_itor
{
	public:
		void operator+(int n)
		{
			std::cout << "array_itor: " << __func__ << std::endl;
		}
};

int main()
{
	list_itor li;
	array_itor ai;
	move_n_step_list(li, 2);
	move_n_step_array(ai, 3);

	return 0;
}

这下,好了,数组型迭代器可以发挥自己随机访问的优势了,但是,这颗毒瘤留给了使用这些算法的客户。他要时刻记着他用的是链表迭代器还是数组迭代器。


此时,traits登场(应有掌声)

traits就是个特性渣取机,它能识别出来一个迭代器是链表的还是数组的,是不是很NB。其实,说白了,也就那回事。

#include <iostream>

class list_itor
{
	public:
		void operator++(int)
		{
			std::cout << "list_itor: " << __func__ << std::endl;
		}
};
class array_itor
{
	public:
		void operator+(int n)
		{
			std::cout << "array_itor: " << __func__ << std::endl;
		}
};

// 定义两种迭代器的类型,仅仅为了实现函数重载
struct list_itor_type {};
struct array_itor_type {};

template <typename ITERATOR>
struct traits
{
};
// 针对链表迭代器的特化
template <>
struct traits<list_itor>
{
	typedef list_itor_type itor_type;
};
// 针对数组迭代器的特化
template <>
struct traits<array_itor>
{
	typedef array_itor_type itor_type;
};

// 内部方法,不应该暴露
template <typename ITERATOR>
void __move_n_step(ITERATOR &itor, int n, list_itor_type)
{
	for (int i = 0; i < n; i++)
		itor++;
}
// 内部方法,不应该暴露
template <typename ITERATOR>
void __move_n_step(ITERATOR &itor, int n, array_itor_type)
{
	itor.operator+(n);
}

// 外部方法,供客户调用
template <typename ITERATOR>
void move_n_step(ITERATOR &itor, int n)
{
	__move_n_step(itor, n, typename traits<ITERATOR>::itor_type());
}

int main()
{
	list_itor li;
	array_itor ai;
	// 客户再也不想要时刻记者用的是什么迭代器了
	move_n_step(li, 2);
	move_n_step(ai, 3);

	return 0;
}

是不是很爽,读STL源码,就会发现,各种容器与迭代器都要实现value_type,pointer_type,difference,reference等,就是这个道理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值