文章目录
- 标准库特殊设施
- 17.1tuple类型
- 17.1.1定义和初始化tuple
- 访问tuple的成员
- 关系和相等运算符
- 17.1.2使用tuple返回多个值
- 17.2bitset类型(后续需要时再详细了解)
- 17.3正则表达式
- 17.4随机数
- bernoulli_distribution类
- 17.5IO库再探
标准库特殊设施
17.1tuple类型
tuple
(定义在tuple
头文件中)是类似pair
的模板。不同tuple
类型的成员类型也不相同,但一个tuple
可以有任意数量的成员。每个确定的tuple
类型的成员数目是固定的,但一个tuple
类型的成员数目可以与另一个tuple
类型不同。
当希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示这些数据时,tuple
是非常有用的。
17.1.1定义和初始化tuple
当定义一个
tuple
时,需要指出每个成员的类型:
tuple<size_t, size_t, size_t> threeD; // 三个成员都设置为0,值初始化。
tuple<string, vector<double>, int, list<int>> someVal("constants", {3.14, 2.718}, 42, {0, 1, 2, 3, 4, 5});
// 使用初始化来推断tuple的类型:tuple<const char*, int, double>
auto item = make_tuple("0-999-78345-X", 3, 20.00);
访问tuple的成员
// 尖括号中的值必须是一个整型常量表达式
auto book = get<0>(item); // 返回item的第一个成员
auto cnt = get<1>(item); // 返回item的第二个成员
auto price = get<2>(item) / cnt; // 返回item的最后一个成员
get<2>(item) *= 0.8; // 打折20%
如果不知道一个
tuple
准确的类型细节信息,可以用两个辅助类模板来查询tuple
成员的数量和类型:
typedef decltype(item) trans; // trans是item的类型
// 返回trans类型对象中成员的数量
size_t sz = tuple_size<trans>::value; // 返回3
// cnt的类型与item中第二个成员相同
tuple_element<1, trans>::type cnt = get<1>(item); // cnt是一个int
关系和相等运算符
只有两个
tuple
具有相同数量的成员时,才可以比较它们。而且,为了使用tuple
的相等或不等运算符,对每对成员使用==
运算符必须都是合法的;为了使用关系运算符,对每对成员使用<
必须都是合法的:
tuple<string, string> duo("1", "2");
tuple<size_t, size_t> twoD(1, 2);
bool b = (duo == twoD); // 错误:不能比较size_t和string。
tuple<size_t, size_t, size_t> threeD(1, 2, 3);
b = (twoD < threeD); // 错误:成员数量不同。
tuple<size_t, size_t> origin(0, 0);
b = (origin < twoD); // 正确:b为true。
17.1.2使用tuple返回多个值
tuple
的一个常见用途是从一个函数返回多个值。
// 书店可能是多家连锁书店中的一家。每家书店都有一个销售记录文件,保存每本书近期的销售数据。
// 可能希望在所有书店中查询某本书的销售情况。
// 假定每家书店都有一个销售记录文件。每个文件都将每本书的所有销售记录存放在一起。进一步假设
// 已有一个函数可以读取这些销售记录文件,为每个书店创建一个vector<Sales_data>,并将这些vector
// 保存在vector的vector中:vector<vector<Sales_data>> files。
// matches有三个成员:一家书店的索引和两个指向书店vector中元素的迭代器。
typedef tuple<vector<Sales_data>::size_type,
vector<Sales_data>::const_iterator,
vector<Sales_data>::const_iterator> matches;
// files保存每家书店的销售记录。
// findBook返回一个vector,每家销售了给定书籍的书店在其中都有一项。
vector<matches> findBook(const vector<vector<Sales_data>> &files, const string &book) {
vector<matches> ret; // 初始化为空vector
// 对每家书店,查找与给定书籍匹配的记录范围(如果存在的话)。
for (auto it = files.cbegin(); it != files.cend(); ++it) {
// 查找具有相同ISBN的Sales_data范围
auto found = equal_range(it->cbegin(), it->cend(), book, compareIsbn);
if (found.first != found.second) { // 此书店销售了给定书籍
// 记住此书店的索引及匹配的范围
ret.push_back(make_tuple(it - files.cbegin(), found.first, found.second));
}
}
return ret; // 如果未找到匹配记录的话,ret为空。
}
void reportResults(istream &in, ostream &os, const vector<vector<Sales_data>> &files) {
string s; // 要查找的书
while (in >> s) {
auto trans = findBook(files, s); // 销售了这本书的书店
if (trans.empty()) {
cout << s << " not found in any stores" << endl;
continue; // 获得下一本要查找的书
}
for (const auto &store : trans) { // 对每家销售了给定书籍的书店
// get<n>返回store中tuple的指定的成员
os << "store " << get<0>(store) << " sales: "
<< accumulate(get<1>(store), get<2>(store), Sales_data(s))
<< endl;
}
}
}