pair源码
pair类定义于通用工具<utility>
头文件中。STL
或者更广泛的说,C++标准库的这种文件组织方式,深刻地影响着软件设计结构。简单地说,也都有一个文件夹或者包或者模块,软件开发过程中可能用到的工具类或者方法,统一放在这些文件集合中。
当一个函数或者接口需要返回两个或者更多的值时,以及在一些情况下需要成对出现一些值时,pair便会是其中的一个选择,当然pair不限于两个数,也可实现pair的pair,pair也是一个模板类。
pair的源码其实非常简单:
// T1和T2可以是不同的类型
// T1和T2甚至都可以是pair模板
template<typename T1, typename T2>
struct pair
{
typedef T1 first_type;
typedef T2 second_type;
// 为了让程序能够处理pair的两个值,
// C++标准库使用struct进行封装(所有成员都是public),
// 也即提供了“直接访问对应数据成员的能力”
T1 first;
T2 second; // 两个成员变量
pair():first(T1()), second(T2()){}
// pair<T1, T2> p;
// default构造函数,建立一个pair,
// 其元素类型分别为T1和T2,
// 各自以其default构造函数(T1(), T2())初始化
pair(const T1& a, const T2& b) :first(a), second(b) {}
// pair<T1, T2> p(val1, val2);
// 以val1(T1类型),val2(T2类型)为初值进行初始化
}
pair的pair
比如我们要返回一个集合的一些统计数据,如最大值、最小值以及中位数,也就是我们需要一个刚好能够容纳三个数的容器
。
template<typename T, typename CONT>
::pair<T, ::pair<T, T>> stats(CONT& coll)
// ::域作用符是为了与库函数做区分
{
std::sort(coll.begin(), coll.end());
// 排序的目的是为了找到中位数
auto minVal = *(coll.begin());
auto maxVal = *(--coll.end());
size_t n = coll.size();
auto median = (n%2 == 0) ? (coll[n/2] + coll[n/2-1])/2
: coll[n/2];
return ::pair<T, ::pair<T, T>>(median, ::pair<T, T>(minVal, maxVal));
}
客户端程序:
int main(int, char**)
{
std::vector<int> ivec{0, 1, 2, 3, 4};
auto values = stats<int, vector<int>>(ivec);
std::cout << "min: " << values.second.first
<< "max: " << values.second.second
<< "median: " << values.first << std::endl;
return 0;
}
pair与map容器的关系
对map
而言,所有元素都会根据元素的键值自动被排序,map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一个元素(first)被视为键值,第二个元素被视为实值(value),map不允许两个元素有相同的键值。
玩转pair
- 让输出流适配pair类型数据
template<typename T1, typename T2>
std::ostream& operator<<(std::ostream& os, const std::pair<T1, T2>& p)
{
return os << "[" << p.first << ", " << p.second << "]" ;
}
- 暂时忘却模板,便捷函数
std::make_pair
显然这里的std::make_pair
是一个模板函数,如此才可使用其便捷的自动类型推导。
// 由于之前的关于输出流的运算符重载
std::cout << std::pair<std::string, int>("InsideZhang", 23) << std::endl;
我们来看不显式使用模板的情况:
std::cout << std::make_pair("InsideZhang", 23) << std::endl;
有了自动类型推导(无模板而无不模板)更是让其如虎添翼:
auto p = std::make_pair("InsideZhang", 23);
根据客户端程序,我们可轻松给出它的内部实现:
template<typename T1, typename T2>
std::pair<T1, T2> make_pair(const T1& x, const T2& y)
{
return std::pair<T1, T2>(x, y);
}
再来一个自动类型推导的版本:
template<typename T1, typename T2>
auto make_pair(const T1& x, const T2& y) -> decltype(std::pair<T1, T2>(x, y))
{
return std::pair<T1, T2>(x, y);
}